10b57cec5SDimitry Andric //===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Hacks and fun related to the code rewriter. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Rewrite/Frontend/ASTConsumers.h" 140b57cec5SDimitry Andric #include "clang/AST/AST.h" 150b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h" 160b57cec5SDimitry Andric #include "clang/AST/Attr.h" 170b57cec5SDimitry Andric #include "clang/AST/ParentMap.h" 180b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h" 190b57cec5SDimitry Andric #include "clang/Basic/Diagnostic.h" 200b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h" 210b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 220b57cec5SDimitry Andric #include "clang/Config/config.h" 230b57cec5SDimitry Andric #include "clang/Lex/Lexer.h" 240b57cec5SDimitry Andric #include "clang/Rewrite/Core/Rewriter.h" 250b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 260b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 270b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 280b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 290b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 300b57cec5SDimitry Andric #include <memory> 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric #if CLANG_ENABLE_OBJC_REWRITER 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric using namespace clang; 350b57cec5SDimitry Andric using llvm::utostr; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric namespace { 380b57cec5SDimitry Andric class RewriteObjC : public ASTConsumer { 390b57cec5SDimitry Andric protected: 400b57cec5SDimitry Andric enum { 410b57cec5SDimitry Andric BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 420b57cec5SDimitry Andric block, ... */ 430b57cec5SDimitry Andric BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 440b57cec5SDimitry Andric BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the 450b57cec5SDimitry Andric __block variable */ 460b57cec5SDimitry Andric BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 470b57cec5SDimitry Andric helpers */ 480b57cec5SDimitry Andric BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 490b57cec5SDimitry Andric support routines */ 500b57cec5SDimitry Andric BLOCK_BYREF_CURRENT_MAX = 256 510b57cec5SDimitry Andric }; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric enum { 540b57cec5SDimitry Andric BLOCK_NEEDS_FREE = (1 << 24), 550b57cec5SDimitry Andric BLOCK_HAS_COPY_DISPOSE = (1 << 25), 560b57cec5SDimitry Andric BLOCK_HAS_CXX_OBJ = (1 << 26), 570b57cec5SDimitry Andric BLOCK_IS_GC = (1 << 27), 580b57cec5SDimitry Andric BLOCK_IS_GLOBAL = (1 << 28), 590b57cec5SDimitry Andric BLOCK_HAS_DESCRIPTOR = (1 << 29) 600b57cec5SDimitry Andric }; 610b57cec5SDimitry Andric static const int OBJC_ABI_VERSION = 7; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric Rewriter Rewrite; 640b57cec5SDimitry Andric DiagnosticsEngine &Diags; 650b57cec5SDimitry Andric const LangOptions &LangOpts; 660b57cec5SDimitry Andric ASTContext *Context; 670b57cec5SDimitry Andric SourceManager *SM; 680b57cec5SDimitry Andric TranslationUnitDecl *TUDecl; 690b57cec5SDimitry Andric FileID MainFileID; 700b57cec5SDimitry Andric const char *MainFileStart, *MainFileEnd; 710b57cec5SDimitry Andric Stmt *CurrentBody; 720b57cec5SDimitry Andric ParentMap *PropParentMap; // created lazily. 730b57cec5SDimitry Andric std::string InFileName; 740b57cec5SDimitry Andric std::unique_ptr<raw_ostream> OutFile; 750b57cec5SDimitry Andric std::string Preamble; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric TypeDecl *ProtocolTypeDecl; 780b57cec5SDimitry Andric VarDecl *GlobalVarDecl; 790b57cec5SDimitry Andric unsigned RewriteFailedDiag; 800b57cec5SDimitry Andric // ObjC string constant support. 810b57cec5SDimitry Andric unsigned NumObjCStringLiterals; 820b57cec5SDimitry Andric VarDecl *ConstantStringClassReference; 830b57cec5SDimitry Andric RecordDecl *NSStringRecord; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric // ObjC foreach break/continue generation support. 860b57cec5SDimitry Andric int BcLabelCount; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric unsigned TryFinallyContainsReturnDiag; 890b57cec5SDimitry Andric // Needed for super. 900b57cec5SDimitry Andric ObjCMethodDecl *CurMethodDef; 910b57cec5SDimitry Andric RecordDecl *SuperStructDecl; 920b57cec5SDimitry Andric RecordDecl *ConstantStringDecl; 930b57cec5SDimitry Andric 940b57cec5SDimitry Andric FunctionDecl *MsgSendFunctionDecl; 950b57cec5SDimitry Andric FunctionDecl *MsgSendSuperFunctionDecl; 960b57cec5SDimitry Andric FunctionDecl *MsgSendStretFunctionDecl; 970b57cec5SDimitry Andric FunctionDecl *MsgSendSuperStretFunctionDecl; 980b57cec5SDimitry Andric FunctionDecl *MsgSendFpretFunctionDecl; 990b57cec5SDimitry Andric FunctionDecl *GetClassFunctionDecl; 1000b57cec5SDimitry Andric FunctionDecl *GetMetaClassFunctionDecl; 1010b57cec5SDimitry Andric FunctionDecl *GetSuperClassFunctionDecl; 1020b57cec5SDimitry Andric FunctionDecl *SelGetUidFunctionDecl; 1030b57cec5SDimitry Andric FunctionDecl *CFStringFunctionDecl; 1040b57cec5SDimitry Andric FunctionDecl *SuperConstructorFunctionDecl; 1050b57cec5SDimitry Andric FunctionDecl *CurFunctionDef; 1060b57cec5SDimitry Andric FunctionDecl *CurFunctionDeclToDeclareForBlock; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric /* Misc. containers needed for meta-data rewrite. */ 1090b57cec5SDimitry Andric SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; 1100b57cec5SDimitry Andric SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; 1110b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; 1120b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; 1130b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls; 1140b57cec5SDimitry Andric llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; 1150b57cec5SDimitry Andric SmallVector<Stmt *, 32> Stmts; 1160b57cec5SDimitry Andric SmallVector<int, 8> ObjCBcLabelNo; 1170b57cec5SDimitry Andric // Remember all the @protocol(<expr>) expressions. 1180b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric llvm::DenseSet<uint64_t> CopyDestroyCache; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // Block expressions. 1230b57cec5SDimitry Andric SmallVector<BlockExpr *, 32> Blocks; 1240b57cec5SDimitry Andric SmallVector<int, 32> InnerDeclRefsCount; 1250b57cec5SDimitry Andric SmallVector<DeclRefExpr *, 32> InnerDeclRefs; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric SmallVector<DeclRefExpr *, 32> BlockDeclRefs; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // Block related declarations. 1300b57cec5SDimitry Andric SmallVector<ValueDecl *, 8> BlockByCopyDecls; 1310b57cec5SDimitry Andric llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; 1320b57cec5SDimitry Andric SmallVector<ValueDecl *, 8> BlockByRefDecls; 1330b57cec5SDimitry Andric llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; 1340b57cec5SDimitry Andric llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; 1350b57cec5SDimitry Andric llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; 1360b57cec5SDimitry Andric llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls; 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric // This maps an original source AST to it's rewritten form. This allows 1410b57cec5SDimitry Andric // us to avoid rewriting the same node twice (which is very uncommon). 1420b57cec5SDimitry Andric // This is needed to support some of the exotic property rewriting. 1430b57cec5SDimitry Andric llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric // Needed for header files being rewritten 1460b57cec5SDimitry Andric bool IsHeader; 1470b57cec5SDimitry Andric bool SilenceRewriteMacroWarning; 1480b57cec5SDimitry Andric bool objc_impl_method; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric bool DisableReplaceStmt; 1510b57cec5SDimitry Andric class DisableReplaceStmtScope { 1520b57cec5SDimitry Andric RewriteObjC &R; 1530b57cec5SDimitry Andric bool SavedValue; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric public: 1560b57cec5SDimitry Andric DisableReplaceStmtScope(RewriteObjC &R) 1570b57cec5SDimitry Andric : R(R), SavedValue(R.DisableReplaceStmt) { 1580b57cec5SDimitry Andric R.DisableReplaceStmt = true; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric ~DisableReplaceStmtScope() { 1620b57cec5SDimitry Andric R.DisableReplaceStmt = SavedValue; 1630b57cec5SDimitry Andric } 1640b57cec5SDimitry Andric }; 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric void InitializeCommon(ASTContext &context); 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric public: 1690b57cec5SDimitry Andric // Top Level Driver code. 1700b57cec5SDimitry Andric bool HandleTopLevelDecl(DeclGroupRef D) override { 1710b57cec5SDimitry Andric for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 1720b57cec5SDimitry Andric if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) { 1730b57cec5SDimitry Andric if (!Class->isThisDeclarationADefinition()) { 1740b57cec5SDimitry Andric RewriteForwardClassDecl(D); 1750b57cec5SDimitry Andric break; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) { 1800b57cec5SDimitry Andric if (!Proto->isThisDeclarationADefinition()) { 1810b57cec5SDimitry Andric RewriteForwardProtocolDecl(D); 1820b57cec5SDimitry Andric break; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric } 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric HandleTopLevelSingleDecl(*I); 1870b57cec5SDimitry Andric } 1880b57cec5SDimitry Andric return true; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric void HandleTopLevelSingleDecl(Decl *D); 1920b57cec5SDimitry Andric void HandleDeclInMainFile(Decl *D); 1930b57cec5SDimitry Andric RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS, 1940b57cec5SDimitry Andric DiagnosticsEngine &D, const LangOptions &LOpts, 1950b57cec5SDimitry Andric bool silenceMacroWarn); 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric ~RewriteObjC() override {} 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric void HandleTranslationUnit(ASTContext &C) override; 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric void ReplaceStmt(Stmt *Old, Stmt *New) { 2020b57cec5SDimitry Andric ReplaceStmtWithRange(Old, New, Old->getSourceRange()); 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { 2060b57cec5SDimitry Andric assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's"); 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric Stmt *ReplacingStmt = ReplacedNodes[Old]; 2090b57cec5SDimitry Andric if (ReplacingStmt) 2100b57cec5SDimitry Andric return; // We can't rewrite the same node twice. 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric if (DisableReplaceStmt) 2130b57cec5SDimitry Andric return; 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric // Measure the old text. 2160b57cec5SDimitry Andric int Size = Rewrite.getRangeSize(SrcRange); 2170b57cec5SDimitry Andric if (Size == -1) { 2180b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag) 2190b57cec5SDimitry Andric << Old->getSourceRange(); 2200b57cec5SDimitry Andric return; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric // Get the new text. 2230b57cec5SDimitry Andric std::string SStr; 2240b57cec5SDimitry Andric llvm::raw_string_ostream S(SStr); 2250b57cec5SDimitry Andric New->printPretty(S, nullptr, PrintingPolicy(LangOpts)); 2260b57cec5SDimitry Andric const std::string &Str = S.str(); 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric // If replacement succeeded or warning disabled return with no warning. 2290b57cec5SDimitry Andric if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) { 2300b57cec5SDimitry Andric ReplacedNodes[Old] = New; 2310b57cec5SDimitry Andric return; 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric if (SilenceRewriteMacroWarning) 2340b57cec5SDimitry Andric return; 2350b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag) 2360b57cec5SDimitry Andric << Old->getSourceRange(); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric void InsertText(SourceLocation Loc, StringRef Str, 2400b57cec5SDimitry Andric bool InsertAfter = true) { 2410b57cec5SDimitry Andric // If insertion succeeded or warning disabled return with no warning. 2420b57cec5SDimitry Andric if (!Rewrite.InsertText(Loc, Str, InsertAfter) || 2430b57cec5SDimitry Andric SilenceRewriteMacroWarning) 2440b57cec5SDimitry Andric return; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric void ReplaceText(SourceLocation Start, unsigned OrigLength, 2500b57cec5SDimitry Andric StringRef Str) { 2510b57cec5SDimitry Andric // If removal succeeded or warning disabled return with no warning. 2520b57cec5SDimitry Andric if (!Rewrite.ReplaceText(Start, OrigLength, Str) || 2530b57cec5SDimitry Andric SilenceRewriteMacroWarning) 2540b57cec5SDimitry Andric return; 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric // Syntactic Rewriting. 2600b57cec5SDimitry Andric void RewriteRecordBody(RecordDecl *RD); 2610b57cec5SDimitry Andric void RewriteInclude(); 2620b57cec5SDimitry Andric void RewriteForwardClassDecl(DeclGroupRef D); 2630b57cec5SDimitry Andric void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG); 2640b57cec5SDimitry Andric void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 2650b57cec5SDimitry Andric const std::string &typedefString); 2660b57cec5SDimitry Andric void RewriteImplementations(); 2670b57cec5SDimitry Andric void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 2680b57cec5SDimitry Andric ObjCImplementationDecl *IMD, 2690b57cec5SDimitry Andric ObjCCategoryImplDecl *CID); 2700b57cec5SDimitry Andric void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); 2710b57cec5SDimitry Andric void RewriteImplementationDecl(Decl *Dcl); 2720b57cec5SDimitry Andric void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 2730b57cec5SDimitry Andric ObjCMethodDecl *MDecl, std::string &ResultStr); 2740b57cec5SDimitry Andric void RewriteTypeIntoString(QualType T, std::string &ResultStr, 2750b57cec5SDimitry Andric const FunctionType *&FPRetType); 2760b57cec5SDimitry Andric void RewriteByRefString(std::string &ResultStr, const std::string &Name, 2770b57cec5SDimitry Andric ValueDecl *VD, bool def=false); 2780b57cec5SDimitry Andric void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); 2790b57cec5SDimitry Andric void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); 2800b57cec5SDimitry Andric void RewriteForwardProtocolDecl(DeclGroupRef D); 2810b57cec5SDimitry Andric void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG); 2820b57cec5SDimitry Andric void RewriteMethodDeclaration(ObjCMethodDecl *Method); 2830b57cec5SDimitry Andric void RewriteProperty(ObjCPropertyDecl *prop); 2840b57cec5SDimitry Andric void RewriteFunctionDecl(FunctionDecl *FD); 2850b57cec5SDimitry Andric void RewriteBlockPointerType(std::string& Str, QualType Type); 2860b57cec5SDimitry Andric void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD); 2870b57cec5SDimitry Andric void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); 2880b57cec5SDimitry Andric void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); 2890b57cec5SDimitry Andric void RewriteTypeOfDecl(VarDecl *VD); 2900b57cec5SDimitry Andric void RewriteObjCQualifiedInterfaceTypes(Expr *E); 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric // Expression Rewriting. 2930b57cec5SDimitry Andric Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); 2940b57cec5SDimitry Andric Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); 2950b57cec5SDimitry Andric Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo); 2960b57cec5SDimitry Andric Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo); 2970b57cec5SDimitry Andric Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); 2980b57cec5SDimitry Andric Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); 2990b57cec5SDimitry Andric Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); 3000b57cec5SDimitry Andric Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); 3010b57cec5SDimitry Andric void RewriteTryReturnStmts(Stmt *S); 3020b57cec5SDimitry Andric void RewriteSyncReturnStmts(Stmt *S, std::string buf); 3030b57cec5SDimitry Andric Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); 3040b57cec5SDimitry Andric Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); 3050b57cec5SDimitry Andric Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); 3060b57cec5SDimitry Andric Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 3070b57cec5SDimitry Andric SourceLocation OrigEnd); 3080b57cec5SDimitry Andric Stmt *RewriteBreakStmt(BreakStmt *S); 3090b57cec5SDimitry Andric Stmt *RewriteContinueStmt(ContinueStmt *S); 3100b57cec5SDimitry Andric void RewriteCastExpr(CStyleCastExpr *CE); 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric // Block rewriting. 3130b57cec5SDimitry Andric void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric // Block specific rewrite rules. 3160b57cec5SDimitry Andric void RewriteBlockPointerDecl(NamedDecl *VD); 3170b57cec5SDimitry Andric void RewriteByRefVar(VarDecl *VD); 3180b57cec5SDimitry Andric Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD); 3190b57cec5SDimitry Andric Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); 3200b57cec5SDimitry Andric void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 3230b57cec5SDimitry Andric std::string &Result); 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric void Initialize(ASTContext &context) override = 0; 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric // Metadata Rewriting. 3280b57cec5SDimitry Andric virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0; 3290b57cec5SDimitry Andric virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, 3300b57cec5SDimitry Andric StringRef prefix, 3310b57cec5SDimitry Andric StringRef ClassName, 3320b57cec5SDimitry Andric std::string &Result) = 0; 3330b57cec5SDimitry Andric virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 3340b57cec5SDimitry Andric std::string &Result) = 0; 3350b57cec5SDimitry Andric virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 3360b57cec5SDimitry Andric StringRef prefix, 3370b57cec5SDimitry Andric StringRef ClassName, 3380b57cec5SDimitry Andric std::string &Result) = 0; 3390b57cec5SDimitry Andric virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 3400b57cec5SDimitry Andric std::string &Result) = 0; 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric // Rewriting ivar access 3430b57cec5SDimitry Andric virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0; 3440b57cec5SDimitry Andric virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 3450b57cec5SDimitry Andric std::string &Result) = 0; 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric // Misc. AST transformation routines. Sometimes they end up calling 3480b57cec5SDimitry Andric // rewriting routines on the new ASTs. 3490b57cec5SDimitry Andric CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 3500b57cec5SDimitry Andric ArrayRef<Expr *> Args, 3510b57cec5SDimitry Andric SourceLocation StartLoc=SourceLocation(), 3520b57cec5SDimitry Andric SourceLocation EndLoc=SourceLocation()); 3530b57cec5SDimitry Andric CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, 3540b57cec5SDimitry Andric QualType msgSendType, 3550b57cec5SDimitry Andric QualType returnType, 3560b57cec5SDimitry Andric SmallVectorImpl<QualType> &ArgTypes, 3570b57cec5SDimitry Andric SmallVectorImpl<Expr*> &MsgExprs, 3580b57cec5SDimitry Andric ObjCMethodDecl *Method); 3590b57cec5SDimitry Andric Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, 3600b57cec5SDimitry Andric SourceLocation StartLoc=SourceLocation(), 3610b57cec5SDimitry Andric SourceLocation EndLoc=SourceLocation()); 3620b57cec5SDimitry Andric 3630b57cec5SDimitry Andric void SynthCountByEnumWithState(std::string &buf); 3640b57cec5SDimitry Andric void SynthMsgSendFunctionDecl(); 3650b57cec5SDimitry Andric void SynthMsgSendSuperFunctionDecl(); 3660b57cec5SDimitry Andric void SynthMsgSendStretFunctionDecl(); 3670b57cec5SDimitry Andric void SynthMsgSendFpretFunctionDecl(); 3680b57cec5SDimitry Andric void SynthMsgSendSuperStretFunctionDecl(); 3690b57cec5SDimitry Andric void SynthGetClassFunctionDecl(); 3700b57cec5SDimitry Andric void SynthGetMetaClassFunctionDecl(); 3710b57cec5SDimitry Andric void SynthGetSuperClassFunctionDecl(); 3720b57cec5SDimitry Andric void SynthSelGetUidFunctionDecl(); 3730b57cec5SDimitry Andric void SynthSuperConstructorFunctionDecl(); 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); 3760b57cec5SDimitry Andric std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 3770b57cec5SDimitry Andric StringRef funcName, std::string Tag); 3780b57cec5SDimitry Andric std::string SynthesizeBlockFunc(BlockExpr *CE, int i, 3790b57cec5SDimitry Andric StringRef funcName, std::string Tag); 3800b57cec5SDimitry Andric std::string SynthesizeBlockImpl(BlockExpr *CE, 3810b57cec5SDimitry Andric std::string Tag, std::string Desc); 3820b57cec5SDimitry Andric std::string SynthesizeBlockDescriptor(std::string DescTag, 3830b57cec5SDimitry Andric std::string ImplTag, 3840b57cec5SDimitry Andric int i, StringRef funcName, 3850b57cec5SDimitry Andric unsigned hasCopy); 3860b57cec5SDimitry Andric Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); 3870b57cec5SDimitry Andric void SynthesizeBlockLiterals(SourceLocation FunLocStart, 3880b57cec5SDimitry Andric StringRef FunName); 3890b57cec5SDimitry Andric FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); 3900b57cec5SDimitry Andric Stmt *SynthBlockInitExpr(BlockExpr *Exp, 3910b57cec5SDimitry Andric const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs); 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric // Misc. helper routines. 3940b57cec5SDimitry Andric QualType getProtocolType(); 3950b57cec5SDimitry Andric void WarnAboutReturnGotoStmts(Stmt *S); 3960b57cec5SDimitry Andric void HasReturnStmts(Stmt *S, bool &hasReturns); 3970b57cec5SDimitry Andric void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); 3980b57cec5SDimitry Andric void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); 3990b57cec5SDimitry Andric void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric bool IsDeclStmtInForeachHeader(DeclStmt *DS); 4020b57cec5SDimitry Andric void CollectBlockDeclRefInfo(BlockExpr *Exp); 4030b57cec5SDimitry Andric void GetBlockDeclRefExprs(Stmt *S); 4040b57cec5SDimitry Andric void GetInnerBlockDeclRefExprs(Stmt *S, 4050b57cec5SDimitry Andric SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs, 4060b57cec5SDimitry Andric llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts); 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric // We avoid calling Type::isBlockPointerType(), since it operates on the 4090b57cec5SDimitry Andric // canonical type. We only care if the top-level type is a closure pointer. 4100b57cec5SDimitry Andric bool isTopLevelBlockPointerType(QualType T) { 4110b57cec5SDimitry Andric return isa<BlockPointerType>(T); 4120b57cec5SDimitry Andric } 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric /// convertBlockPointerToFunctionPointer - Converts a block-pointer type 4150b57cec5SDimitry Andric /// to a function pointer type and upon success, returns true; false 4160b57cec5SDimitry Andric /// otherwise. 4170b57cec5SDimitry Andric bool convertBlockPointerToFunctionPointer(QualType &T) { 4180b57cec5SDimitry Andric if (isTopLevelBlockPointerType(T)) { 419a7dea167SDimitry Andric const auto *BPT = T->castAs<BlockPointerType>(); 4200b57cec5SDimitry Andric T = Context->getPointerType(BPT->getPointeeType()); 4210b57cec5SDimitry Andric return true; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric return false; 4240b57cec5SDimitry Andric } 4250b57cec5SDimitry Andric 4260b57cec5SDimitry Andric bool needToScanForQualifiers(QualType T); 4270b57cec5SDimitry Andric QualType getSuperStructType(); 4280b57cec5SDimitry Andric QualType getConstantStringStructType(); 4290b57cec5SDimitry Andric QualType convertFunctionTypeOfBlocks(const FunctionType *FT); 4300b57cec5SDimitry Andric bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric void convertToUnqualifiedObjCType(QualType &T) { 4330b57cec5SDimitry Andric if (T->isObjCQualifiedIdType()) 4340b57cec5SDimitry Andric T = Context->getObjCIdType(); 4350b57cec5SDimitry Andric else if (T->isObjCQualifiedClassType()) 4360b57cec5SDimitry Andric T = Context->getObjCClassType(); 4370b57cec5SDimitry Andric else if (T->isObjCObjectPointerType() && 4380b57cec5SDimitry Andric T->getPointeeType()->isObjCQualifiedInterfaceType()) { 4390b57cec5SDimitry Andric if (const ObjCObjectPointerType * OBJPT = 4400b57cec5SDimitry Andric T->getAsObjCInterfacePointerType()) { 4410b57cec5SDimitry Andric const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); 4420b57cec5SDimitry Andric T = QualType(IFaceT, 0); 4430b57cec5SDimitry Andric T = Context->getPointerType(T); 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric // FIXME: This predicate seems like it would be useful to add to ASTContext. 4490b57cec5SDimitry Andric bool isObjCType(QualType T) { 4500b57cec5SDimitry Andric if (!LangOpts.ObjC) 4510b57cec5SDimitry Andric return false; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || 4560b57cec5SDimitry Andric OCT == Context->getCanonicalType(Context->getObjCClassType())) 4570b57cec5SDimitry Andric return true; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric if (const PointerType *PT = OCT->getAs<PointerType>()) { 4600b57cec5SDimitry Andric if (isa<ObjCInterfaceType>(PT->getPointeeType()) || 4610b57cec5SDimitry Andric PT->getPointeeType()->isObjCQualifiedIdType()) 4620b57cec5SDimitry Andric return true; 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric return false; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric bool PointerTypeTakesAnyBlockArguments(QualType QT); 4670b57cec5SDimitry Andric bool PointerTypeTakesAnyObjCQualifiedType(QualType QT); 4680b57cec5SDimitry Andric void GetExtentOfArgList(const char *Name, const char *&LParen, 4690b57cec5SDimitry Andric const char *&RParen); 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric void QuoteDoublequotes(std::string &From, std::string &To) { 4720b57cec5SDimitry Andric for (unsigned i = 0; i < From.length(); i++) { 4730b57cec5SDimitry Andric if (From[i] == '"') 4740b57cec5SDimitry Andric To += "\\\""; 4750b57cec5SDimitry Andric else 4760b57cec5SDimitry Andric To += From[i]; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric QualType getSimpleFunctionType(QualType result, 4810b57cec5SDimitry Andric ArrayRef<QualType> args, 4820b57cec5SDimitry Andric bool variadic = false) { 4830b57cec5SDimitry Andric if (result == Context->getObjCInstanceType()) 4840b57cec5SDimitry Andric result = Context->getObjCIdType(); 4850b57cec5SDimitry Andric FunctionProtoType::ExtProtoInfo fpi; 4860b57cec5SDimitry Andric fpi.Variadic = variadic; 4870b57cec5SDimitry Andric return Context->getFunctionType(result, args, fpi); 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric // Helper function: create a CStyleCastExpr with trivial type source info. 4910b57cec5SDimitry Andric CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, 4920b57cec5SDimitry Andric CastKind Kind, Expr *E) { 4930b57cec5SDimitry Andric TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); 494fe6060f1SDimitry Andric return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr, 495e8d8bef9SDimitry Andric FPOptionsOverride(), TInfo, 496e8d8bef9SDimitry Andric SourceLocation(), SourceLocation()); 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric StringLiteral *getStringLiteral(StringRef Str) { 5000b57cec5SDimitry Andric QualType StrType = Context->getConstantArrayType( 501a7dea167SDimitry Andric Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr, 502*5f757f3fSDimitry Andric ArraySizeModifier::Normal, 0); 503*5f757f3fSDimitry Andric return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary, 5040b57cec5SDimitry Andric /*Pascal=*/false, StrType, SourceLocation()); 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric }; 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric class RewriteObjCFragileABI : public RewriteObjC { 5090b57cec5SDimitry Andric public: 5100b57cec5SDimitry Andric RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS, 5110b57cec5SDimitry Andric DiagnosticsEngine &D, const LangOptions &LOpts, 5120b57cec5SDimitry Andric bool silenceMacroWarn) 5130b57cec5SDimitry Andric : RewriteObjC(inFile, std::move(OS), D, LOpts, silenceMacroWarn) {} 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric ~RewriteObjCFragileABI() override {} 5160b57cec5SDimitry Andric void Initialize(ASTContext &context) override; 5170b57cec5SDimitry Andric 5180b57cec5SDimitry Andric // Rewriting metadata 5190b57cec5SDimitry Andric template<typename MethodIterator> 5200b57cec5SDimitry Andric void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 5210b57cec5SDimitry Andric MethodIterator MethodEnd, 5220b57cec5SDimitry Andric bool IsInstanceMethod, 5230b57cec5SDimitry Andric StringRef prefix, 5240b57cec5SDimitry Andric StringRef ClassName, 5250b57cec5SDimitry Andric std::string &Result); 5260b57cec5SDimitry Andric void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 5270b57cec5SDimitry Andric StringRef prefix, StringRef ClassName, 5280b57cec5SDimitry Andric std::string &Result) override; 5290b57cec5SDimitry Andric void RewriteObjCProtocolListMetaData( 5300b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &Prots, 5310b57cec5SDimitry Andric StringRef prefix, StringRef ClassName, std::string &Result) override; 5320b57cec5SDimitry Andric void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 5330b57cec5SDimitry Andric std::string &Result) override; 5340b57cec5SDimitry Andric void RewriteMetaDataIntoBuffer(std::string &Result) override; 5350b57cec5SDimitry Andric void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 5360b57cec5SDimitry Andric std::string &Result) override; 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric // Rewriting ivar 5390b57cec5SDimitry Andric void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 5400b57cec5SDimitry Andric std::string &Result) override; 5410b57cec5SDimitry Andric Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) override; 5420b57cec5SDimitry Andric }; 5430b57cec5SDimitry Andric } // end anonymous namespace 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, 5460b57cec5SDimitry Andric NamedDecl *D) { 5470b57cec5SDimitry Andric if (const FunctionProtoType *fproto 5480b57cec5SDimitry Andric = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) { 5490b57cec5SDimitry Andric for (const auto &I : fproto->param_types()) 5500b57cec5SDimitry Andric if (isTopLevelBlockPointerType(I)) { 5510b57cec5SDimitry Andric // All the args are checked/rewritten. Don't call twice! 5520b57cec5SDimitry Andric RewriteBlockPointerDecl(D); 5530b57cec5SDimitry Andric break; 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { 5590b57cec5SDimitry Andric const PointerType *PT = funcType->getAs<PointerType>(); 5600b57cec5SDimitry Andric if (PT && PointerTypeTakesAnyBlockArguments(funcType)) 5610b57cec5SDimitry Andric RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric static bool IsHeaderFile(const std::string &Filename) { 5650b57cec5SDimitry Andric std::string::size_type DotPos = Filename.rfind('.'); 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric if (DotPos == std::string::npos) { 5680b57cec5SDimitry Andric // no file extension 5690b57cec5SDimitry Andric return false; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5724824e7fdSDimitry Andric std::string Ext = Filename.substr(DotPos + 1); 5730b57cec5SDimitry Andric // C header: .h 5740b57cec5SDimitry Andric // C++ header: .hh or .H; 5750b57cec5SDimitry Andric return Ext == "h" || Ext == "hh" || Ext == "H"; 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric RewriteObjC::RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS, 5790b57cec5SDimitry Andric DiagnosticsEngine &D, const LangOptions &LOpts, 5800b57cec5SDimitry Andric bool silenceMacroWarn) 5810b57cec5SDimitry Andric : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)), 5820b57cec5SDimitry Andric SilenceRewriteMacroWarning(silenceMacroWarn) { 5830b57cec5SDimitry Andric IsHeader = IsHeaderFile(inFile); 5840b57cec5SDimitry Andric RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 5850b57cec5SDimitry Andric "rewriting sub-expression within a macro (may not be correct)"); 5860b57cec5SDimitry Andric TryFinallyContainsReturnDiag = Diags.getCustomDiagID( 5870b57cec5SDimitry Andric DiagnosticsEngine::Warning, 5880b57cec5SDimitry Andric "rewriter doesn't support user-specified control flow semantics " 5890b57cec5SDimitry Andric "for @try/@finally (code may not execute properly)"); 5900b57cec5SDimitry Andric } 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> 5930b57cec5SDimitry Andric clang::CreateObjCRewriter(const std::string &InFile, 5940b57cec5SDimitry Andric std::unique_ptr<raw_ostream> OS, 5950b57cec5SDimitry Andric DiagnosticsEngine &Diags, const LangOptions &LOpts, 5960b57cec5SDimitry Andric bool SilenceRewriteMacroWarning) { 597a7dea167SDimitry Andric return std::make_unique<RewriteObjCFragileABI>( 5980b57cec5SDimitry Andric InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning); 5990b57cec5SDimitry Andric } 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric void RewriteObjC::InitializeCommon(ASTContext &context) { 6020b57cec5SDimitry Andric Context = &context; 6030b57cec5SDimitry Andric SM = &Context->getSourceManager(); 6040b57cec5SDimitry Andric TUDecl = Context->getTranslationUnitDecl(); 6050b57cec5SDimitry Andric MsgSendFunctionDecl = nullptr; 6060b57cec5SDimitry Andric MsgSendSuperFunctionDecl = nullptr; 6070b57cec5SDimitry Andric MsgSendStretFunctionDecl = nullptr; 6080b57cec5SDimitry Andric MsgSendSuperStretFunctionDecl = nullptr; 6090b57cec5SDimitry Andric MsgSendFpretFunctionDecl = nullptr; 6100b57cec5SDimitry Andric GetClassFunctionDecl = nullptr; 6110b57cec5SDimitry Andric GetMetaClassFunctionDecl = nullptr; 6120b57cec5SDimitry Andric GetSuperClassFunctionDecl = nullptr; 6130b57cec5SDimitry Andric SelGetUidFunctionDecl = nullptr; 6140b57cec5SDimitry Andric CFStringFunctionDecl = nullptr; 6150b57cec5SDimitry Andric ConstantStringClassReference = nullptr; 6160b57cec5SDimitry Andric NSStringRecord = nullptr; 6170b57cec5SDimitry Andric CurMethodDef = nullptr; 6180b57cec5SDimitry Andric CurFunctionDef = nullptr; 6190b57cec5SDimitry Andric CurFunctionDeclToDeclareForBlock = nullptr; 6200b57cec5SDimitry Andric GlobalVarDecl = nullptr; 6210b57cec5SDimitry Andric SuperStructDecl = nullptr; 6220b57cec5SDimitry Andric ProtocolTypeDecl = nullptr; 6230b57cec5SDimitry Andric ConstantStringDecl = nullptr; 6240b57cec5SDimitry Andric BcLabelCount = 0; 6250b57cec5SDimitry Andric SuperConstructorFunctionDecl = nullptr; 6260b57cec5SDimitry Andric NumObjCStringLiterals = 0; 6270b57cec5SDimitry Andric PropParentMap = nullptr; 6280b57cec5SDimitry Andric CurrentBody = nullptr; 6290b57cec5SDimitry Andric DisableReplaceStmt = false; 6300b57cec5SDimitry Andric objc_impl_method = false; 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric // Get the ID and start/end of the main file. 6330b57cec5SDimitry Andric MainFileID = SM->getMainFileID(); 634e8d8bef9SDimitry Andric llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID); 635e8d8bef9SDimitry Andric MainFileStart = MainBuf.getBufferStart(); 636e8d8bef9SDimitry Andric MainFileEnd = MainBuf.getBufferEnd(); 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts()); 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6420b57cec5SDimitry Andric // Top Level Driver Code 6430b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { 6460b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 6470b57cec5SDimitry Andric return; 6480b57cec5SDimitry Andric 6490b57cec5SDimitry Andric // Two cases: either the decl could be in the main file, or it could be in a 6500b57cec5SDimitry Andric // #included file. If the former, rewrite it now. If the later, check to see 6510b57cec5SDimitry Andric // if we rewrote the #include/#import. 6520b57cec5SDimitry Andric SourceLocation Loc = D->getLocation(); 6530b57cec5SDimitry Andric Loc = SM->getExpansionLoc(Loc); 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric // If this is for a builtin, ignore it. 6560b57cec5SDimitry Andric if (Loc.isInvalid()) return; 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric // Look for built-in declarations that we need to refer during the rewrite. 6590b57cec5SDimitry Andric if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 6600b57cec5SDimitry Andric RewriteFunctionDecl(FD); 6610b57cec5SDimitry Andric } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) { 6620b57cec5SDimitry Andric // declared in <Foundation/NSString.h> 6630b57cec5SDimitry Andric if (FVD->getName() == "_NSConstantStringClassReference") { 6640b57cec5SDimitry Andric ConstantStringClassReference = FVD; 6650b57cec5SDimitry Andric return; 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { 6680b57cec5SDimitry Andric if (ID->isThisDeclarationADefinition()) 6690b57cec5SDimitry Andric RewriteInterfaceDecl(ID); 6700b57cec5SDimitry Andric } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { 6710b57cec5SDimitry Andric RewriteCategoryDecl(CD); 6720b57cec5SDimitry Andric } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { 6730b57cec5SDimitry Andric if (PD->isThisDeclarationADefinition()) 6740b57cec5SDimitry Andric RewriteProtocolDecl(PD); 6750b57cec5SDimitry Andric } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { 6760b57cec5SDimitry Andric // Recurse into linkage specifications 6770b57cec5SDimitry Andric for (DeclContext::decl_iterator DI = LSD->decls_begin(), 6780b57cec5SDimitry Andric DIEnd = LSD->decls_end(); 6790b57cec5SDimitry Andric DI != DIEnd; ) { 6800b57cec5SDimitry Andric if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) { 6810b57cec5SDimitry Andric if (!IFace->isThisDeclarationADefinition()) { 6820b57cec5SDimitry Andric SmallVector<Decl *, 8> DG; 6830b57cec5SDimitry Andric SourceLocation StartLoc = IFace->getBeginLoc(); 6840b57cec5SDimitry Andric do { 6850b57cec5SDimitry Andric if (isa<ObjCInterfaceDecl>(*DI) && 6860b57cec5SDimitry Andric !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() && 6870b57cec5SDimitry Andric StartLoc == (*DI)->getBeginLoc()) 6880b57cec5SDimitry Andric DG.push_back(*DI); 6890b57cec5SDimitry Andric else 6900b57cec5SDimitry Andric break; 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric ++DI; 6930b57cec5SDimitry Andric } while (DI != DIEnd); 6940b57cec5SDimitry Andric RewriteForwardClassDecl(DG); 6950b57cec5SDimitry Andric continue; 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) { 7000b57cec5SDimitry Andric if (!Proto->isThisDeclarationADefinition()) { 7010b57cec5SDimitry Andric SmallVector<Decl *, 8> DG; 7020b57cec5SDimitry Andric SourceLocation StartLoc = Proto->getBeginLoc(); 7030b57cec5SDimitry Andric do { 7040b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(*DI) && 7050b57cec5SDimitry Andric !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() && 7060b57cec5SDimitry Andric StartLoc == (*DI)->getBeginLoc()) 7070b57cec5SDimitry Andric DG.push_back(*DI); 7080b57cec5SDimitry Andric else 7090b57cec5SDimitry Andric break; 7100b57cec5SDimitry Andric 7110b57cec5SDimitry Andric ++DI; 7120b57cec5SDimitry Andric } while (DI != DIEnd); 7130b57cec5SDimitry Andric RewriteForwardProtocolDecl(DG); 7140b57cec5SDimitry Andric continue; 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric HandleTopLevelSingleDecl(*DI); 7190b57cec5SDimitry Andric ++DI; 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric // If we have a decl in the main file, see if we should rewrite it. 7230b57cec5SDimitry Andric if (SM->isWrittenInMainFile(Loc)) 7240b57cec5SDimitry Andric return HandleDeclInMainFile(D); 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7280b57cec5SDimitry Andric // Syntactic (non-AST) Rewriting Code 7290b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric void RewriteObjC::RewriteInclude() { 7320b57cec5SDimitry Andric SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); 7330b57cec5SDimitry Andric StringRef MainBuf = SM->getBufferData(MainFileID); 7340b57cec5SDimitry Andric const char *MainBufStart = MainBuf.begin(); 7350b57cec5SDimitry Andric const char *MainBufEnd = MainBuf.end(); 7360b57cec5SDimitry Andric size_t ImportLen = strlen("import"); 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric // Loop over the whole file, looking for includes. 7390b57cec5SDimitry Andric for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { 7400b57cec5SDimitry Andric if (*BufPtr == '#') { 7410b57cec5SDimitry Andric if (++BufPtr == MainBufEnd) 7420b57cec5SDimitry Andric return; 7430b57cec5SDimitry Andric while (*BufPtr == ' ' || *BufPtr == '\t') 7440b57cec5SDimitry Andric if (++BufPtr == MainBufEnd) 7450b57cec5SDimitry Andric return; 7460b57cec5SDimitry Andric if (!strncmp(BufPtr, "import", ImportLen)) { 7470b57cec5SDimitry Andric // replace import with include 7480b57cec5SDimitry Andric SourceLocation ImportLoc = 7490b57cec5SDimitry Andric LocStart.getLocWithOffset(BufPtr-MainBufStart); 7500b57cec5SDimitry Andric ReplaceText(ImportLoc, ImportLen, "include"); 7510b57cec5SDimitry Andric BufPtr += ImportLen; 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric } 7560b57cec5SDimitry Andric 7570b57cec5SDimitry Andric static std::string getIvarAccessString(ObjCIvarDecl *OID) { 7580b57cec5SDimitry Andric const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface(); 7590b57cec5SDimitry Andric std::string S; 7600b57cec5SDimitry Andric S = "((struct "; 7610b57cec5SDimitry Andric S += ClassDecl->getIdentifier()->getName(); 7620b57cec5SDimitry Andric S += "_IMPL *)self)->"; 7630b57cec5SDimitry Andric S += OID->getName(); 7640b57cec5SDimitry Andric return S; 7650b57cec5SDimitry Andric } 7660b57cec5SDimitry Andric 7670b57cec5SDimitry Andric void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 7680b57cec5SDimitry Andric ObjCImplementationDecl *IMD, 7690b57cec5SDimitry Andric ObjCCategoryImplDecl *CID) { 7700b57cec5SDimitry Andric static bool objcGetPropertyDefined = false; 7710b57cec5SDimitry Andric static bool objcSetPropertyDefined = false; 7720b57cec5SDimitry Andric SourceLocation startLoc = PID->getBeginLoc(); 7730b57cec5SDimitry Andric InsertText(startLoc, "// "); 7740b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 7750b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @synthesize location"); 7760b57cec5SDimitry Andric const char *semiBuf = strchr(startBuf, ';'); 7770b57cec5SDimitry Andric assert((*semiBuf == ';') && "@synthesize: can't find ';'"); 7780b57cec5SDimitry Andric SourceLocation onePastSemiLoc = 7790b57cec5SDimitry Andric startLoc.getLocWithOffset(semiBuf-startBuf+1); 7800b57cec5SDimitry Andric 7810b57cec5SDimitry Andric if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 7820b57cec5SDimitry Andric return; // FIXME: is this correct? 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric // Generate the 'getter' function. 7850b57cec5SDimitry Andric ObjCPropertyDecl *PD = PID->getPropertyDecl(); 7860b57cec5SDimitry Andric ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric if (!OID) 7890b57cec5SDimitry Andric return; 790480093f4SDimitry Andric 7910b57cec5SDimitry Andric unsigned Attributes = PD->getPropertyAttributes(); 792480093f4SDimitry Andric if (PID->getGetterMethodDecl() && !PID->getGetterMethodDecl()->isDefined()) { 7935ffd83dbSDimitry Andric bool GenGetProperty = 7945ffd83dbSDimitry Andric !(Attributes & ObjCPropertyAttribute::kind_nonatomic) && 7955ffd83dbSDimitry Andric (Attributes & (ObjCPropertyAttribute::kind_retain | 7965ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_copy)); 7970b57cec5SDimitry Andric std::string Getr; 7980b57cec5SDimitry Andric if (GenGetProperty && !objcGetPropertyDefined) { 7990b57cec5SDimitry Andric objcGetPropertyDefined = true; 8000b57cec5SDimitry Andric // FIXME. Is this attribute correct in all cases? 8010b57cec5SDimitry Andric Getr = "\nextern \"C\" __declspec(dllimport) " 8020b57cec5SDimitry Andric "id objc_getProperty(id, SEL, long, bool);\n"; 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric RewriteObjCMethodDecl(OID->getContainingInterface(), 805480093f4SDimitry Andric PID->getGetterMethodDecl(), Getr); 8060b57cec5SDimitry Andric Getr += "{ "; 8070b57cec5SDimitry Andric // Synthesize an explicit cast to gain access to the ivar. 8080b57cec5SDimitry Andric // See objc-act.c:objc_synthesize_new_getter() for details. 8090b57cec5SDimitry Andric if (GenGetProperty) { 8100b57cec5SDimitry Andric // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) 8110b57cec5SDimitry Andric Getr += "typedef "; 8120b57cec5SDimitry Andric const FunctionType *FPRetType = nullptr; 813480093f4SDimitry Andric RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr, 8140b57cec5SDimitry Andric FPRetType); 8150b57cec5SDimitry Andric Getr += " _TYPE"; 8160b57cec5SDimitry Andric if (FPRetType) { 8170b57cec5SDimitry Andric Getr += ")"; // close the precedence "scope" for "*". 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric // Now, emit the argument types (if any). 8200b57cec5SDimitry Andric if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){ 8210b57cec5SDimitry Andric Getr += "("; 8220b57cec5SDimitry Andric for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { 8230b57cec5SDimitry Andric if (i) Getr += ", "; 8240b57cec5SDimitry Andric std::string ParamStr = 8250b57cec5SDimitry Andric FT->getParamType(i).getAsString(Context->getPrintingPolicy()); 8260b57cec5SDimitry Andric Getr += ParamStr; 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric if (FT->isVariadic()) { 8290b57cec5SDimitry Andric if (FT->getNumParams()) 8300b57cec5SDimitry Andric Getr += ", "; 8310b57cec5SDimitry Andric Getr += "..."; 8320b57cec5SDimitry Andric } 8330b57cec5SDimitry Andric Getr += ")"; 8340b57cec5SDimitry Andric } else 8350b57cec5SDimitry Andric Getr += "()"; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric Getr += ";\n"; 8380b57cec5SDimitry Andric Getr += "return (_TYPE)"; 8390b57cec5SDimitry Andric Getr += "objc_getProperty(self, _cmd, "; 8400b57cec5SDimitry Andric RewriteIvarOffsetComputation(OID, Getr); 8410b57cec5SDimitry Andric Getr += ", 1)"; 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric else 8440b57cec5SDimitry Andric Getr += "return " + getIvarAccessString(OID); 8450b57cec5SDimitry Andric Getr += "; }"; 8460b57cec5SDimitry Andric InsertText(onePastSemiLoc, Getr); 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 849480093f4SDimitry Andric if (PD->isReadOnly() || !PID->getSetterMethodDecl() || 850480093f4SDimitry Andric PID->getSetterMethodDecl()->isDefined()) 8510b57cec5SDimitry Andric return; 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric // Generate the 'setter' function. 8540b57cec5SDimitry Andric std::string Setr; 8555ffd83dbSDimitry Andric bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain | 8565ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_copy); 8570b57cec5SDimitry Andric if (GenSetProperty && !objcSetPropertyDefined) { 8580b57cec5SDimitry Andric objcSetPropertyDefined = true; 8590b57cec5SDimitry Andric // FIXME. Is this attribute correct in all cases? 8600b57cec5SDimitry Andric Setr = "\nextern \"C\" __declspec(dllimport) " 8610b57cec5SDimitry Andric "void objc_setProperty (id, SEL, long, id, bool, bool);\n"; 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric RewriteObjCMethodDecl(OID->getContainingInterface(), 865480093f4SDimitry Andric PID->getSetterMethodDecl(), Setr); 8660b57cec5SDimitry Andric Setr += "{ "; 8670b57cec5SDimitry Andric // Synthesize an explicit cast to initialize the ivar. 8680b57cec5SDimitry Andric // See objc-act.c:objc_synthesize_new_setter() for details. 8690b57cec5SDimitry Andric if (GenSetProperty) { 8700b57cec5SDimitry Andric Setr += "objc_setProperty (self, _cmd, "; 8710b57cec5SDimitry Andric RewriteIvarOffsetComputation(OID, Setr); 8720b57cec5SDimitry Andric Setr += ", (id)"; 8730b57cec5SDimitry Andric Setr += PD->getName(); 8740b57cec5SDimitry Andric Setr += ", "; 8755ffd83dbSDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_nonatomic) 8760b57cec5SDimitry Andric Setr += "0, "; 8770b57cec5SDimitry Andric else 8780b57cec5SDimitry Andric Setr += "1, "; 8795ffd83dbSDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_copy) 8800b57cec5SDimitry Andric Setr += "1)"; 8810b57cec5SDimitry Andric else 8820b57cec5SDimitry Andric Setr += "0)"; 8830b57cec5SDimitry Andric } 8840b57cec5SDimitry Andric else { 8850b57cec5SDimitry Andric Setr += getIvarAccessString(OID) + " = "; 8860b57cec5SDimitry Andric Setr += PD->getName(); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric Setr += "; }"; 8890b57cec5SDimitry Andric InsertText(onePastSemiLoc, Setr); 8900b57cec5SDimitry Andric } 8910b57cec5SDimitry Andric 8920b57cec5SDimitry Andric static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, 8930b57cec5SDimitry Andric std::string &typedefString) { 8940b57cec5SDimitry Andric typedefString += "#ifndef _REWRITER_typedef_"; 8950b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 8960b57cec5SDimitry Andric typedefString += "\n"; 8970b57cec5SDimitry Andric typedefString += "#define _REWRITER_typedef_"; 8980b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 8990b57cec5SDimitry Andric typedefString += "\n"; 9000b57cec5SDimitry Andric typedefString += "typedef struct objc_object "; 9010b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 9020b57cec5SDimitry Andric typedefString += ";\n#endif\n"; 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 9060b57cec5SDimitry Andric const std::string &typedefString) { 9070b57cec5SDimitry Andric SourceLocation startLoc = ClassDecl->getBeginLoc(); 9080b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 9090b57cec5SDimitry Andric const char *semiPtr = strchr(startBuf, ';'); 9100b57cec5SDimitry Andric // Replace the @class with typedefs corresponding to the classes. 9110b57cec5SDimitry Andric ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString); 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) { 9150b57cec5SDimitry Andric std::string typedefString; 9160b57cec5SDimitry Andric for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 9170b57cec5SDimitry Andric ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I); 9180b57cec5SDimitry Andric if (I == D.begin()) { 9190b57cec5SDimitry Andric // Translate to typedef's that forward reference structs with the same name 9200b57cec5SDimitry Andric // as the class. As a convenience, we include the original declaration 9210b57cec5SDimitry Andric // as a comment. 9220b57cec5SDimitry Andric typedefString += "// @class "; 9230b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 9240b57cec5SDimitry Andric typedefString += ";\n"; 9250b57cec5SDimitry Andric } 9260b57cec5SDimitry Andric RewriteOneForwardClassDecl(ForwardDecl, typedefString); 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric DeclGroupRef::iterator I = D.begin(); 9290b57cec5SDimitry Andric RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString); 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric void RewriteObjC::RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &D) { 9330b57cec5SDimitry Andric std::string typedefString; 9340b57cec5SDimitry Andric for (unsigned i = 0; i < D.size(); i++) { 9350b57cec5SDimitry Andric ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]); 9360b57cec5SDimitry Andric if (i == 0) { 9370b57cec5SDimitry Andric typedefString += "// @class "; 9380b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 9390b57cec5SDimitry Andric typedefString += ";\n"; 9400b57cec5SDimitry Andric } 9410b57cec5SDimitry Andric RewriteOneForwardClassDecl(ForwardDecl, typedefString); 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString); 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric 9460b57cec5SDimitry Andric void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { 9470b57cec5SDimitry Andric // When method is a synthesized one, such as a getter/setter there is 9480b57cec5SDimitry Andric // nothing to rewrite. 9490b57cec5SDimitry Andric if (Method->isImplicit()) 9500b57cec5SDimitry Andric return; 9510b57cec5SDimitry Andric SourceLocation LocStart = Method->getBeginLoc(); 9520b57cec5SDimitry Andric SourceLocation LocEnd = Method->getEndLoc(); 9530b57cec5SDimitry Andric 9540b57cec5SDimitry Andric if (SM->getExpansionLineNumber(LocEnd) > 9550b57cec5SDimitry Andric SM->getExpansionLineNumber(LocStart)) { 9560b57cec5SDimitry Andric InsertText(LocStart, "#if 0\n"); 9570b57cec5SDimitry Andric ReplaceText(LocEnd, 1, ";\n#endif\n"); 9580b57cec5SDimitry Andric } else { 9590b57cec5SDimitry Andric InsertText(LocStart, "// "); 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) { 9640b57cec5SDimitry Andric SourceLocation Loc = prop->getAtLoc(); 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric ReplaceText(Loc, 0, "// "); 9670b57cec5SDimitry Andric // FIXME: handle properties that are declared across multiple lines. 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric 9700b57cec5SDimitry Andric void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { 9710b57cec5SDimitry Andric SourceLocation LocStart = CatDecl->getBeginLoc(); 9720b57cec5SDimitry Andric 9730b57cec5SDimitry Andric // FIXME: handle category headers that are declared across multiple lines. 9740b57cec5SDimitry Andric ReplaceText(LocStart, 0, "// "); 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric for (auto *I : CatDecl->instance_properties()) 9770b57cec5SDimitry Andric RewriteProperty(I); 9780b57cec5SDimitry Andric for (auto *I : CatDecl->instance_methods()) 9790b57cec5SDimitry Andric RewriteMethodDeclaration(I); 9800b57cec5SDimitry Andric for (auto *I : CatDecl->class_methods()) 9810b57cec5SDimitry Andric RewriteMethodDeclaration(I); 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric // Lastly, comment out the @end. 9840b57cec5SDimitry Andric ReplaceText(CatDecl->getAtEndRange().getBegin(), 9850b57cec5SDimitry Andric strlen("@end"), "/* @end */"); 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { 9890b57cec5SDimitry Andric SourceLocation LocStart = PDecl->getBeginLoc(); 9900b57cec5SDimitry Andric assert(PDecl->isThisDeclarationADefinition()); 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric // FIXME: handle protocol headers that are declared across multiple lines. 9930b57cec5SDimitry Andric ReplaceText(LocStart, 0, "// "); 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric for (auto *I : PDecl->instance_methods()) 9960b57cec5SDimitry Andric RewriteMethodDeclaration(I); 9970b57cec5SDimitry Andric for (auto *I : PDecl->class_methods()) 9980b57cec5SDimitry Andric RewriteMethodDeclaration(I); 9990b57cec5SDimitry Andric for (auto *I : PDecl->instance_properties()) 10000b57cec5SDimitry Andric RewriteProperty(I); 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric // Lastly, comment out the @end. 10030b57cec5SDimitry Andric SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); 10040b57cec5SDimitry Andric ReplaceText(LocEnd, strlen("@end"), "/* @end */"); 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric // Must comment out @optional/@required 10070b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 10080b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 10090b57cec5SDimitry Andric for (const char *p = startBuf; p < endBuf; p++) { 10100b57cec5SDimitry Andric if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { 10110b57cec5SDimitry Andric SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 10120b57cec5SDimitry Andric ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { 10160b57cec5SDimitry Andric SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 10170b57cec5SDimitry Andric ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric } 10200b57cec5SDimitry Andric } 10210b57cec5SDimitry Andric } 10220b57cec5SDimitry Andric 10230b57cec5SDimitry Andric void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) { 10240b57cec5SDimitry Andric SourceLocation LocStart = (*D.begin())->getBeginLoc(); 10250b57cec5SDimitry Andric if (LocStart.isInvalid()) 10260b57cec5SDimitry Andric llvm_unreachable("Invalid SourceLocation"); 10270b57cec5SDimitry Andric // FIXME: handle forward protocol that are declared across multiple lines. 10280b57cec5SDimitry Andric ReplaceText(LocStart, 0, "// "); 10290b57cec5SDimitry Andric } 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric void 10320b57cec5SDimitry Andric RewriteObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) { 10330b57cec5SDimitry Andric SourceLocation LocStart = DG[0]->getBeginLoc(); 10340b57cec5SDimitry Andric if (LocStart.isInvalid()) 10350b57cec5SDimitry Andric llvm_unreachable("Invalid SourceLocation"); 10360b57cec5SDimitry Andric // FIXME: handle forward protocol that are declared across multiple lines. 10370b57cec5SDimitry Andric ReplaceText(LocStart, 0, "// "); 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr, 10410b57cec5SDimitry Andric const FunctionType *&FPRetType) { 10420b57cec5SDimitry Andric if (T->isObjCQualifiedIdType()) 10430b57cec5SDimitry Andric ResultStr += "id"; 10440b57cec5SDimitry Andric else if (T->isFunctionPointerType() || 10450b57cec5SDimitry Andric T->isBlockPointerType()) { 10460b57cec5SDimitry Andric // needs special handling, since pointer-to-functions have special 10470b57cec5SDimitry Andric // syntax (where a decaration models use). 10480b57cec5SDimitry Andric QualType retType = T; 10490b57cec5SDimitry Andric QualType PointeeTy; 10500b57cec5SDimitry Andric if (const PointerType* PT = retType->getAs<PointerType>()) 10510b57cec5SDimitry Andric PointeeTy = PT->getPointeeType(); 10520b57cec5SDimitry Andric else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) 10530b57cec5SDimitry Andric PointeeTy = BPT->getPointeeType(); 10540b57cec5SDimitry Andric if ((FPRetType = PointeeTy->getAs<FunctionType>())) { 10550b57cec5SDimitry Andric ResultStr += 10560b57cec5SDimitry Andric FPRetType->getReturnType().getAsString(Context->getPrintingPolicy()); 10570b57cec5SDimitry Andric ResultStr += "(*"; 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric } else 10600b57cec5SDimitry Andric ResultStr += T.getAsString(Context->getPrintingPolicy()); 10610b57cec5SDimitry Andric } 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric void RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 10640b57cec5SDimitry Andric ObjCMethodDecl *OMD, 10650b57cec5SDimitry Andric std::string &ResultStr) { 10660b57cec5SDimitry Andric //fprintf(stderr,"In RewriteObjCMethodDecl\n"); 10670b57cec5SDimitry Andric const FunctionType *FPRetType = nullptr; 10680b57cec5SDimitry Andric ResultStr += "\nstatic "; 10690b57cec5SDimitry Andric RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType); 10700b57cec5SDimitry Andric ResultStr += " "; 10710b57cec5SDimitry Andric 10720b57cec5SDimitry Andric // Unique method name 10730b57cec5SDimitry Andric std::string NameStr; 10740b57cec5SDimitry Andric 10750b57cec5SDimitry Andric if (OMD->isInstanceMethod()) 10760b57cec5SDimitry Andric NameStr += "_I_"; 10770b57cec5SDimitry Andric else 10780b57cec5SDimitry Andric NameStr += "_C_"; 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andric NameStr += IDecl->getNameAsString(); 10810b57cec5SDimitry Andric NameStr += "_"; 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric if (ObjCCategoryImplDecl *CID = 10840b57cec5SDimitry Andric dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 10850b57cec5SDimitry Andric NameStr += CID->getNameAsString(); 10860b57cec5SDimitry Andric NameStr += "_"; 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric // Append selector names, replacing ':' with '_' 10890b57cec5SDimitry Andric { 10900b57cec5SDimitry Andric std::string selString = OMD->getSelector().getAsString(); 10910b57cec5SDimitry Andric int len = selString.size(); 10920b57cec5SDimitry Andric for (int i = 0; i < len; i++) 10930b57cec5SDimitry Andric if (selString[i] == ':') 10940b57cec5SDimitry Andric selString[i] = '_'; 10950b57cec5SDimitry Andric NameStr += selString; 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric // Remember this name for metadata emission 10980b57cec5SDimitry Andric MethodInternalNames[OMD] = NameStr; 10990b57cec5SDimitry Andric ResultStr += NameStr; 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric // Rewrite arguments 11020b57cec5SDimitry Andric ResultStr += "("; 11030b57cec5SDimitry Andric 11040b57cec5SDimitry Andric // invisible arguments 11050b57cec5SDimitry Andric if (OMD->isInstanceMethod()) { 11060b57cec5SDimitry Andric QualType selfTy = Context->getObjCInterfaceType(IDecl); 11070b57cec5SDimitry Andric selfTy = Context->getPointerType(selfTy); 11080b57cec5SDimitry Andric if (!LangOpts.MicrosoftExt) { 11090b57cec5SDimitry Andric if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl))) 11100b57cec5SDimitry Andric ResultStr += "struct "; 11110b57cec5SDimitry Andric } 11120b57cec5SDimitry Andric // When rewriting for Microsoft, explicitly omit the structure name. 11130b57cec5SDimitry Andric ResultStr += IDecl->getNameAsString(); 11140b57cec5SDimitry Andric ResultStr += " *"; 11150b57cec5SDimitry Andric } 11160b57cec5SDimitry Andric else 11170b57cec5SDimitry Andric ResultStr += Context->getObjCClassType().getAsString( 11180b57cec5SDimitry Andric Context->getPrintingPolicy()); 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric ResultStr += " self, "; 11210b57cec5SDimitry Andric ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy()); 11220b57cec5SDimitry Andric ResultStr += " _cmd"; 11230b57cec5SDimitry Andric 11240b57cec5SDimitry Andric // Method arguments. 11250b57cec5SDimitry Andric for (const auto *PDecl : OMD->parameters()) { 11260b57cec5SDimitry Andric ResultStr += ", "; 11270b57cec5SDimitry Andric if (PDecl->getType()->isObjCQualifiedIdType()) { 11280b57cec5SDimitry Andric ResultStr += "id "; 11290b57cec5SDimitry Andric ResultStr += PDecl->getNameAsString(); 11300b57cec5SDimitry Andric } else { 11310b57cec5SDimitry Andric std::string Name = PDecl->getNameAsString(); 11320b57cec5SDimitry Andric QualType QT = PDecl->getType(); 11330b57cec5SDimitry Andric // Make sure we convert "t (^)(...)" to "t (*)(...)". 11340b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(QT); 11350b57cec5SDimitry Andric QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 11360b57cec5SDimitry Andric ResultStr += Name; 11370b57cec5SDimitry Andric } 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric if (OMD->isVariadic()) 11400b57cec5SDimitry Andric ResultStr += ", ..."; 11410b57cec5SDimitry Andric ResultStr += ") "; 11420b57cec5SDimitry Andric 11430b57cec5SDimitry Andric if (FPRetType) { 11440b57cec5SDimitry Andric ResultStr += ")"; // close the precedence "scope" for "*". 11450b57cec5SDimitry Andric 11460b57cec5SDimitry Andric // Now, emit the argument types (if any). 11470b57cec5SDimitry Andric if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { 11480b57cec5SDimitry Andric ResultStr += "("; 11490b57cec5SDimitry Andric for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { 11500b57cec5SDimitry Andric if (i) ResultStr += ", "; 11510b57cec5SDimitry Andric std::string ParamStr = 11520b57cec5SDimitry Andric FT->getParamType(i).getAsString(Context->getPrintingPolicy()); 11530b57cec5SDimitry Andric ResultStr += ParamStr; 11540b57cec5SDimitry Andric } 11550b57cec5SDimitry Andric if (FT->isVariadic()) { 11560b57cec5SDimitry Andric if (FT->getNumParams()) 11570b57cec5SDimitry Andric ResultStr += ", "; 11580b57cec5SDimitry Andric ResultStr += "..."; 11590b57cec5SDimitry Andric } 11600b57cec5SDimitry Andric ResultStr += ")"; 11610b57cec5SDimitry Andric } else { 11620b57cec5SDimitry Andric ResultStr += "()"; 11630b57cec5SDimitry Andric } 11640b57cec5SDimitry Andric } 11650b57cec5SDimitry Andric } 11660b57cec5SDimitry Andric 11670b57cec5SDimitry Andric void RewriteObjC::RewriteImplementationDecl(Decl *OID) { 11680b57cec5SDimitry Andric ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); 11690b57cec5SDimitry Andric ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); 1170a7dea167SDimitry Andric assert((IMD || CID) && "Unknown ImplementationDecl"); 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// "); 11730b57cec5SDimitry Andric 11740b57cec5SDimitry Andric for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) { 1175480093f4SDimitry Andric if (!OMD->getBody()) 1176480093f4SDimitry Andric continue; 11770b57cec5SDimitry Andric std::string ResultStr; 11780b57cec5SDimitry Andric RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 11790b57cec5SDimitry Andric SourceLocation LocStart = OMD->getBeginLoc(); 11800b57cec5SDimitry Andric SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc(); 11810b57cec5SDimitry Andric 11820b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 11830b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 11840b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf, ResultStr); 11850b57cec5SDimitry Andric } 11860b57cec5SDimitry Andric 11870b57cec5SDimitry Andric for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) { 1188480093f4SDimitry Andric if (!OMD->getBody()) 1189480093f4SDimitry Andric continue; 11900b57cec5SDimitry Andric std::string ResultStr; 11910b57cec5SDimitry Andric RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 11920b57cec5SDimitry Andric SourceLocation LocStart = OMD->getBeginLoc(); 11930b57cec5SDimitry Andric SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc(); 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 11960b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 11970b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf, ResultStr); 11980b57cec5SDimitry Andric } 11990b57cec5SDimitry Andric for (auto *I : IMD ? IMD->property_impls() : CID->property_impls()) 12000b57cec5SDimitry Andric RewritePropertyImplDecl(I, IMD, CID); 12010b57cec5SDimitry Andric 12020b57cec5SDimitry Andric InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// "); 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 12060b57cec5SDimitry Andric std::string ResultStr; 12070b57cec5SDimitry Andric if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) { 12080b57cec5SDimitry Andric // we haven't seen a forward decl - generate a typedef. 12090b57cec5SDimitry Andric ResultStr = "#ifndef _REWRITER_typedef_"; 12100b57cec5SDimitry Andric ResultStr += ClassDecl->getNameAsString(); 12110b57cec5SDimitry Andric ResultStr += "\n"; 12120b57cec5SDimitry Andric ResultStr += "#define _REWRITER_typedef_"; 12130b57cec5SDimitry Andric ResultStr += ClassDecl->getNameAsString(); 12140b57cec5SDimitry Andric ResultStr += "\n"; 12150b57cec5SDimitry Andric ResultStr += "typedef struct objc_object "; 12160b57cec5SDimitry Andric ResultStr += ClassDecl->getNameAsString(); 12170b57cec5SDimitry Andric ResultStr += ";\n#endif\n"; 12180b57cec5SDimitry Andric // Mark this typedef as having been generated. 12190b57cec5SDimitry Andric ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl()); 12200b57cec5SDimitry Andric } 12210b57cec5SDimitry Andric RewriteObjCInternalStruct(ClassDecl, ResultStr); 12220b57cec5SDimitry Andric 12230b57cec5SDimitry Andric for (auto *I : ClassDecl->instance_properties()) 12240b57cec5SDimitry Andric RewriteProperty(I); 12250b57cec5SDimitry Andric for (auto *I : ClassDecl->instance_methods()) 12260b57cec5SDimitry Andric RewriteMethodDeclaration(I); 12270b57cec5SDimitry Andric for (auto *I : ClassDecl->class_methods()) 12280b57cec5SDimitry Andric RewriteMethodDeclaration(I); 12290b57cec5SDimitry Andric 12300b57cec5SDimitry Andric // Lastly, comment out the @end. 12310b57cec5SDimitry Andric ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), 12320b57cec5SDimitry Andric "/* @end */"); 12330b57cec5SDimitry Andric } 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andric Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) { 12360b57cec5SDimitry Andric SourceRange OldRange = PseudoOp->getSourceRange(); 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric // We just magically know some things about the structure of this 12390b57cec5SDimitry Andric // expression. 12400b57cec5SDimitry Andric ObjCMessageExpr *OldMsg = 12410b57cec5SDimitry Andric cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr( 12420b57cec5SDimitry Andric PseudoOp->getNumSemanticExprs() - 1)); 12430b57cec5SDimitry Andric 12440b57cec5SDimitry Andric // Because the rewriter doesn't allow us to rewrite rewritten code, 12450b57cec5SDimitry Andric // we need to suppress rewriting the sub-statements. 12460b57cec5SDimitry Andric Expr *Base, *RHS; 12470b57cec5SDimitry Andric { 12480b57cec5SDimitry Andric DisableReplaceStmtScope S(*this); 12490b57cec5SDimitry Andric 12500b57cec5SDimitry Andric // Rebuild the base expression if we have one. 12510b57cec5SDimitry Andric Base = nullptr; 12520b57cec5SDimitry Andric if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 12530b57cec5SDimitry Andric Base = OldMsg->getInstanceReceiver(); 12540b57cec5SDimitry Andric Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 12550b57cec5SDimitry Andric Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 12560b57cec5SDimitry Andric } 12570b57cec5SDimitry Andric 12580b57cec5SDimitry Andric // Rebuild the RHS. 12590b57cec5SDimitry Andric RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS(); 12600b57cec5SDimitry Andric RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr(); 12610b57cec5SDimitry Andric RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS)); 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric 12640b57cec5SDimitry Andric // TODO: avoid this copy. 12650b57cec5SDimitry Andric SmallVector<SourceLocation, 1> SelLocs; 12660b57cec5SDimitry Andric OldMsg->getSelectorLocs(SelLocs); 12670b57cec5SDimitry Andric 12680b57cec5SDimitry Andric ObjCMessageExpr *NewMsg = nullptr; 12690b57cec5SDimitry Andric switch (OldMsg->getReceiverKind()) { 12700b57cec5SDimitry Andric case ObjCMessageExpr::Class: 12710b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 12720b57cec5SDimitry Andric OldMsg->getValueKind(), 12730b57cec5SDimitry Andric OldMsg->getLeftLoc(), 12740b57cec5SDimitry Andric OldMsg->getClassReceiverTypeInfo(), 12750b57cec5SDimitry Andric OldMsg->getSelector(), 12760b57cec5SDimitry Andric SelLocs, 12770b57cec5SDimitry Andric OldMsg->getMethodDecl(), 12780b57cec5SDimitry Andric RHS, 12790b57cec5SDimitry Andric OldMsg->getRightLoc(), 12800b57cec5SDimitry Andric OldMsg->isImplicit()); 12810b57cec5SDimitry Andric break; 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andric case ObjCMessageExpr::Instance: 12840b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 12850b57cec5SDimitry Andric OldMsg->getValueKind(), 12860b57cec5SDimitry Andric OldMsg->getLeftLoc(), 12870b57cec5SDimitry Andric Base, 12880b57cec5SDimitry Andric OldMsg->getSelector(), 12890b57cec5SDimitry Andric SelLocs, 12900b57cec5SDimitry Andric OldMsg->getMethodDecl(), 12910b57cec5SDimitry Andric RHS, 12920b57cec5SDimitry Andric OldMsg->getRightLoc(), 12930b57cec5SDimitry Andric OldMsg->isImplicit()); 12940b57cec5SDimitry Andric break; 12950b57cec5SDimitry Andric 12960b57cec5SDimitry Andric case ObjCMessageExpr::SuperClass: 12970b57cec5SDimitry Andric case ObjCMessageExpr::SuperInstance: 12980b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 12990b57cec5SDimitry Andric OldMsg->getValueKind(), 13000b57cec5SDimitry Andric OldMsg->getLeftLoc(), 13010b57cec5SDimitry Andric OldMsg->getSuperLoc(), 13020b57cec5SDimitry Andric OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 13030b57cec5SDimitry Andric OldMsg->getSuperType(), 13040b57cec5SDimitry Andric OldMsg->getSelector(), 13050b57cec5SDimitry Andric SelLocs, 13060b57cec5SDimitry Andric OldMsg->getMethodDecl(), 13070b57cec5SDimitry Andric RHS, 13080b57cec5SDimitry Andric OldMsg->getRightLoc(), 13090b57cec5SDimitry Andric OldMsg->isImplicit()); 13100b57cec5SDimitry Andric break; 13110b57cec5SDimitry Andric } 13120b57cec5SDimitry Andric 13130b57cec5SDimitry Andric Stmt *Replacement = SynthMessageExpr(NewMsg); 13140b57cec5SDimitry Andric ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 13150b57cec5SDimitry Andric return Replacement; 13160b57cec5SDimitry Andric } 13170b57cec5SDimitry Andric 13180b57cec5SDimitry Andric Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) { 13190b57cec5SDimitry Andric SourceRange OldRange = PseudoOp->getSourceRange(); 13200b57cec5SDimitry Andric 13210b57cec5SDimitry Andric // We just magically know some things about the structure of this 13220b57cec5SDimitry Andric // expression. 13230b57cec5SDimitry Andric ObjCMessageExpr *OldMsg = 13240b57cec5SDimitry Andric cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit()); 13250b57cec5SDimitry Andric 13260b57cec5SDimitry Andric // Because the rewriter doesn't allow us to rewrite rewritten code, 13270b57cec5SDimitry Andric // we need to suppress rewriting the sub-statements. 13280b57cec5SDimitry Andric Expr *Base = nullptr; 13290b57cec5SDimitry Andric { 13300b57cec5SDimitry Andric DisableReplaceStmtScope S(*this); 13310b57cec5SDimitry Andric 13320b57cec5SDimitry Andric // Rebuild the base expression if we have one. 13330b57cec5SDimitry Andric if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 13340b57cec5SDimitry Andric Base = OldMsg->getInstanceReceiver(); 13350b57cec5SDimitry Andric Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 13360b57cec5SDimitry Andric Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 13370b57cec5SDimitry Andric } 13380b57cec5SDimitry Andric } 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric // Intentionally empty. 13410b57cec5SDimitry Andric SmallVector<SourceLocation, 1> SelLocs; 13420b57cec5SDimitry Andric SmallVector<Expr*, 1> Args; 13430b57cec5SDimitry Andric 13440b57cec5SDimitry Andric ObjCMessageExpr *NewMsg = nullptr; 13450b57cec5SDimitry Andric switch (OldMsg->getReceiverKind()) { 13460b57cec5SDimitry Andric case ObjCMessageExpr::Class: 13470b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 13480b57cec5SDimitry Andric OldMsg->getValueKind(), 13490b57cec5SDimitry Andric OldMsg->getLeftLoc(), 13500b57cec5SDimitry Andric OldMsg->getClassReceiverTypeInfo(), 13510b57cec5SDimitry Andric OldMsg->getSelector(), 13520b57cec5SDimitry Andric SelLocs, 13530b57cec5SDimitry Andric OldMsg->getMethodDecl(), 13540b57cec5SDimitry Andric Args, 13550b57cec5SDimitry Andric OldMsg->getRightLoc(), 13560b57cec5SDimitry Andric OldMsg->isImplicit()); 13570b57cec5SDimitry Andric break; 13580b57cec5SDimitry Andric 13590b57cec5SDimitry Andric case ObjCMessageExpr::Instance: 13600b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 13610b57cec5SDimitry Andric OldMsg->getValueKind(), 13620b57cec5SDimitry Andric OldMsg->getLeftLoc(), 13630b57cec5SDimitry Andric Base, 13640b57cec5SDimitry Andric OldMsg->getSelector(), 13650b57cec5SDimitry Andric SelLocs, 13660b57cec5SDimitry Andric OldMsg->getMethodDecl(), 13670b57cec5SDimitry Andric Args, 13680b57cec5SDimitry Andric OldMsg->getRightLoc(), 13690b57cec5SDimitry Andric OldMsg->isImplicit()); 13700b57cec5SDimitry Andric break; 13710b57cec5SDimitry Andric 13720b57cec5SDimitry Andric case ObjCMessageExpr::SuperClass: 13730b57cec5SDimitry Andric case ObjCMessageExpr::SuperInstance: 13740b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 13750b57cec5SDimitry Andric OldMsg->getValueKind(), 13760b57cec5SDimitry Andric OldMsg->getLeftLoc(), 13770b57cec5SDimitry Andric OldMsg->getSuperLoc(), 13780b57cec5SDimitry Andric OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 13790b57cec5SDimitry Andric OldMsg->getSuperType(), 13800b57cec5SDimitry Andric OldMsg->getSelector(), 13810b57cec5SDimitry Andric SelLocs, 13820b57cec5SDimitry Andric OldMsg->getMethodDecl(), 13830b57cec5SDimitry Andric Args, 13840b57cec5SDimitry Andric OldMsg->getRightLoc(), 13850b57cec5SDimitry Andric OldMsg->isImplicit()); 13860b57cec5SDimitry Andric break; 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric Stmt *Replacement = SynthMessageExpr(NewMsg); 13900b57cec5SDimitry Andric ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 13910b57cec5SDimitry Andric return Replacement; 13920b57cec5SDimitry Andric } 13930b57cec5SDimitry Andric 13940b57cec5SDimitry Andric /// SynthCountByEnumWithState - To print: 13950b57cec5SDimitry Andric /// ((unsigned int (*) 13960b57cec5SDimitry Andric /// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 13970b57cec5SDimitry Andric /// (void *)objc_msgSend)((id)l_collection, 13980b57cec5SDimitry Andric /// sel_registerName( 13990b57cec5SDimitry Andric /// "countByEnumeratingWithState:objects:count:"), 14000b57cec5SDimitry Andric /// &enumState, 14010b57cec5SDimitry Andric /// (id *)__rw_items, (unsigned int)16) 14020b57cec5SDimitry Andric /// 14030b57cec5SDimitry Andric void RewriteObjC::SynthCountByEnumWithState(std::string &buf) { 14040b57cec5SDimitry Andric buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 14050b57cec5SDimitry Andric "id *, unsigned int))(void *)objc_msgSend)"; 14060b57cec5SDimitry Andric buf += "\n\t\t"; 14070b57cec5SDimitry Andric buf += "((id)l_collection,\n\t\t"; 14080b57cec5SDimitry Andric buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; 14090b57cec5SDimitry Andric buf += "\n\t\t"; 14100b57cec5SDimitry Andric buf += "&enumState, " 14110b57cec5SDimitry Andric "(id *)__rw_items, (unsigned int)16)"; 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach 14150b57cec5SDimitry Andric /// statement to exit to its outer synthesized loop. 14160b57cec5SDimitry Andric /// 14170b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) { 14180b57cec5SDimitry Andric if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 14190b57cec5SDimitry Andric return S; 14200b57cec5SDimitry Andric // replace break with goto __break_label 14210b57cec5SDimitry Andric std::string buf; 14220b57cec5SDimitry Andric 14230b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 14240b57cec5SDimitry Andric buf = "goto __break_label_"; 14250b57cec5SDimitry Andric buf += utostr(ObjCBcLabelNo.back()); 14260b57cec5SDimitry Andric ReplaceText(startLoc, strlen("break"), buf); 14270b57cec5SDimitry Andric 14280b57cec5SDimitry Andric return nullptr; 14290b57cec5SDimitry Andric } 14300b57cec5SDimitry Andric 14310b57cec5SDimitry Andric /// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach 14320b57cec5SDimitry Andric /// statement to continue with its inner synthesized loop. 14330b57cec5SDimitry Andric /// 14340b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { 14350b57cec5SDimitry Andric if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 14360b57cec5SDimitry Andric return S; 14370b57cec5SDimitry Andric // replace continue with goto __continue_label 14380b57cec5SDimitry Andric std::string buf; 14390b57cec5SDimitry Andric 14400b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 14410b57cec5SDimitry Andric buf = "goto __continue_label_"; 14420b57cec5SDimitry Andric buf += utostr(ObjCBcLabelNo.back()); 14430b57cec5SDimitry Andric ReplaceText(startLoc, strlen("continue"), buf); 14440b57cec5SDimitry Andric 14450b57cec5SDimitry Andric return nullptr; 14460b57cec5SDimitry Andric } 14470b57cec5SDimitry Andric 14480b57cec5SDimitry Andric /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. 14490b57cec5SDimitry Andric /// It rewrites: 14500b57cec5SDimitry Andric /// for ( type elem in collection) { stmts; } 14510b57cec5SDimitry Andric 14520b57cec5SDimitry Andric /// Into: 14530b57cec5SDimitry Andric /// { 14540b57cec5SDimitry Andric /// type elem; 14550b57cec5SDimitry Andric /// struct __objcFastEnumerationState enumState = { 0 }; 14560b57cec5SDimitry Andric /// id __rw_items[16]; 14570b57cec5SDimitry Andric /// id l_collection = (id)collection; 14580b57cec5SDimitry Andric /// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 14590b57cec5SDimitry Andric /// objects:__rw_items count:16]; 14600b57cec5SDimitry Andric /// if (limit) { 14610b57cec5SDimitry Andric /// unsigned long startMutations = *enumState.mutationsPtr; 14620b57cec5SDimitry Andric /// do { 14630b57cec5SDimitry Andric /// unsigned long counter = 0; 14640b57cec5SDimitry Andric /// do { 14650b57cec5SDimitry Andric /// if (startMutations != *enumState.mutationsPtr) 14660b57cec5SDimitry Andric /// objc_enumerationMutation(l_collection); 14670b57cec5SDimitry Andric /// elem = (type)enumState.itemsPtr[counter++]; 14680b57cec5SDimitry Andric /// stmts; 14690b57cec5SDimitry Andric /// __continue_label: ; 14700b57cec5SDimitry Andric /// } while (counter < limit); 14710b57cec5SDimitry Andric /// } while (limit = [l_collection countByEnumeratingWithState:&enumState 14720b57cec5SDimitry Andric /// objects:__rw_items count:16]); 14730b57cec5SDimitry Andric /// elem = nil; 14740b57cec5SDimitry Andric /// __break_label: ; 14750b57cec5SDimitry Andric /// } 14760b57cec5SDimitry Andric /// else 14770b57cec5SDimitry Andric /// elem = nil; 14780b57cec5SDimitry Andric /// } 14790b57cec5SDimitry Andric /// 14800b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 14810b57cec5SDimitry Andric SourceLocation OrigEnd) { 14820b57cec5SDimitry Andric assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); 14830b57cec5SDimitry Andric assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 14840b57cec5SDimitry Andric "ObjCForCollectionStmt Statement stack mismatch"); 14850b57cec5SDimitry Andric assert(!ObjCBcLabelNo.empty() && 14860b57cec5SDimitry Andric "ObjCForCollectionStmt - Label No stack empty"); 14870b57cec5SDimitry Andric 14880b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 14890b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 14900b57cec5SDimitry Andric StringRef elementName; 14910b57cec5SDimitry Andric std::string elementTypeAsString; 14920b57cec5SDimitry Andric std::string buf; 14930b57cec5SDimitry Andric buf = "\n{\n\t"; 14940b57cec5SDimitry Andric if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) { 14950b57cec5SDimitry Andric // type elem; 14960b57cec5SDimitry Andric NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl()); 14970b57cec5SDimitry Andric QualType ElementType = cast<ValueDecl>(D)->getType(); 14980b57cec5SDimitry Andric if (ElementType->isObjCQualifiedIdType() || 14990b57cec5SDimitry Andric ElementType->isObjCQualifiedInterfaceType()) 15000b57cec5SDimitry Andric // Simply use 'id' for all qualified types. 15010b57cec5SDimitry Andric elementTypeAsString = "id"; 15020b57cec5SDimitry Andric else 15030b57cec5SDimitry Andric elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy()); 15040b57cec5SDimitry Andric buf += elementTypeAsString; 15050b57cec5SDimitry Andric buf += " "; 15060b57cec5SDimitry Andric elementName = D->getName(); 15070b57cec5SDimitry Andric buf += elementName; 15080b57cec5SDimitry Andric buf += ";\n\t"; 15090b57cec5SDimitry Andric } 15100b57cec5SDimitry Andric else { 15110b57cec5SDimitry Andric DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); 15120b57cec5SDimitry Andric elementName = DR->getDecl()->getName(); 15130b57cec5SDimitry Andric ValueDecl *VD = DR->getDecl(); 15140b57cec5SDimitry Andric if (VD->getType()->isObjCQualifiedIdType() || 15150b57cec5SDimitry Andric VD->getType()->isObjCQualifiedInterfaceType()) 15160b57cec5SDimitry Andric // Simply use 'id' for all qualified types. 15170b57cec5SDimitry Andric elementTypeAsString = "id"; 15180b57cec5SDimitry Andric else 15190b57cec5SDimitry Andric elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy()); 15200b57cec5SDimitry Andric } 15210b57cec5SDimitry Andric 15220b57cec5SDimitry Andric // struct __objcFastEnumerationState enumState = { 0 }; 15230b57cec5SDimitry Andric buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; 15240b57cec5SDimitry Andric // id __rw_items[16]; 15250b57cec5SDimitry Andric buf += "id __rw_items[16];\n\t"; 15260b57cec5SDimitry Andric // id l_collection = (id) 15270b57cec5SDimitry Andric buf += "id l_collection = (id)"; 15280b57cec5SDimitry Andric // Find start location of 'collection' the hard way! 15290b57cec5SDimitry Andric const char *startCollectionBuf = startBuf; 15300b57cec5SDimitry Andric startCollectionBuf += 3; // skip 'for' 15310b57cec5SDimitry Andric startCollectionBuf = strchr(startCollectionBuf, '('); 15320b57cec5SDimitry Andric startCollectionBuf++; // skip '(' 15330b57cec5SDimitry Andric // find 'in' and skip it. 15340b57cec5SDimitry Andric while (*startCollectionBuf != ' ' || 15350b57cec5SDimitry Andric *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' || 15360b57cec5SDimitry Andric (*(startCollectionBuf+3) != ' ' && 15370b57cec5SDimitry Andric *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) 15380b57cec5SDimitry Andric startCollectionBuf++; 15390b57cec5SDimitry Andric startCollectionBuf += 3; 15400b57cec5SDimitry Andric 15410b57cec5SDimitry Andric // Replace: "for (type element in" with string constructed thus far. 15420b57cec5SDimitry Andric ReplaceText(startLoc, startCollectionBuf - startBuf, buf); 15430b57cec5SDimitry Andric // Replace ')' in for '(' type elem in collection ')' with ';' 15440b57cec5SDimitry Andric SourceLocation rightParenLoc = S->getRParenLoc(); 15450b57cec5SDimitry Andric const char *rparenBuf = SM->getCharacterData(rightParenLoc); 15460b57cec5SDimitry Andric SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf); 15470b57cec5SDimitry Andric buf = ";\n\t"; 15480b57cec5SDimitry Andric 15490b57cec5SDimitry Andric // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 15500b57cec5SDimitry Andric // objects:__rw_items count:16]; 15510b57cec5SDimitry Andric // which is synthesized into: 15520b57cec5SDimitry Andric // unsigned int limit = 15530b57cec5SDimitry Andric // ((unsigned int (*) 15540b57cec5SDimitry Andric // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 15550b57cec5SDimitry Andric // (void *)objc_msgSend)((id)l_collection, 15560b57cec5SDimitry Andric // sel_registerName( 15570b57cec5SDimitry Andric // "countByEnumeratingWithState:objects:count:"), 15580b57cec5SDimitry Andric // (struct __objcFastEnumerationState *)&state, 15590b57cec5SDimitry Andric // (id *)__rw_items, (unsigned int)16); 15600b57cec5SDimitry Andric buf += "unsigned long limit =\n\t\t"; 15610b57cec5SDimitry Andric SynthCountByEnumWithState(buf); 15620b57cec5SDimitry Andric buf += ";\n\t"; 15630b57cec5SDimitry Andric /// if (limit) { 15640b57cec5SDimitry Andric /// unsigned long startMutations = *enumState.mutationsPtr; 15650b57cec5SDimitry Andric /// do { 15660b57cec5SDimitry Andric /// unsigned long counter = 0; 15670b57cec5SDimitry Andric /// do { 15680b57cec5SDimitry Andric /// if (startMutations != *enumState.mutationsPtr) 15690b57cec5SDimitry Andric /// objc_enumerationMutation(l_collection); 15700b57cec5SDimitry Andric /// elem = (type)enumState.itemsPtr[counter++]; 15710b57cec5SDimitry Andric buf += "if (limit) {\n\t"; 15720b57cec5SDimitry Andric buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t"; 15730b57cec5SDimitry Andric buf += "do {\n\t\t"; 15740b57cec5SDimitry Andric buf += "unsigned long counter = 0;\n\t\t"; 15750b57cec5SDimitry Andric buf += "do {\n\t\t\t"; 15760b57cec5SDimitry Andric buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t"; 15770b57cec5SDimitry Andric buf += "objc_enumerationMutation(l_collection);\n\t\t\t"; 15780b57cec5SDimitry Andric buf += elementName; 15790b57cec5SDimitry Andric buf += " = ("; 15800b57cec5SDimitry Andric buf += elementTypeAsString; 15810b57cec5SDimitry Andric buf += ")enumState.itemsPtr[counter++];"; 15820b57cec5SDimitry Andric // Replace ')' in for '(' type elem in collection ')' with all of these. 15830b57cec5SDimitry Andric ReplaceText(lparenLoc, 1, buf); 15840b57cec5SDimitry Andric 15850b57cec5SDimitry Andric /// __continue_label: ; 15860b57cec5SDimitry Andric /// } while (counter < limit); 15870b57cec5SDimitry Andric /// } while (limit = [l_collection countByEnumeratingWithState:&enumState 15880b57cec5SDimitry Andric /// objects:__rw_items count:16]); 15890b57cec5SDimitry Andric /// elem = nil; 15900b57cec5SDimitry Andric /// __break_label: ; 15910b57cec5SDimitry Andric /// } 15920b57cec5SDimitry Andric /// else 15930b57cec5SDimitry Andric /// elem = nil; 15940b57cec5SDimitry Andric /// } 15950b57cec5SDimitry Andric /// 15960b57cec5SDimitry Andric buf = ";\n\t"; 15970b57cec5SDimitry Andric buf += "__continue_label_"; 15980b57cec5SDimitry Andric buf += utostr(ObjCBcLabelNo.back()); 15990b57cec5SDimitry Andric buf += ": ;"; 16000b57cec5SDimitry Andric buf += "\n\t\t"; 16010b57cec5SDimitry Andric buf += "} while (counter < limit);\n\t"; 16020b57cec5SDimitry Andric buf += "} while (limit = "; 16030b57cec5SDimitry Andric SynthCountByEnumWithState(buf); 16040b57cec5SDimitry Andric buf += ");\n\t"; 16050b57cec5SDimitry Andric buf += elementName; 16060b57cec5SDimitry Andric buf += " = (("; 16070b57cec5SDimitry Andric buf += elementTypeAsString; 16080b57cec5SDimitry Andric buf += ")0);\n\t"; 16090b57cec5SDimitry Andric buf += "__break_label_"; 16100b57cec5SDimitry Andric buf += utostr(ObjCBcLabelNo.back()); 16110b57cec5SDimitry Andric buf += ": ;\n\t"; 16120b57cec5SDimitry Andric buf += "}\n\t"; 16130b57cec5SDimitry Andric buf += "else\n\t\t"; 16140b57cec5SDimitry Andric buf += elementName; 16150b57cec5SDimitry Andric buf += " = (("; 16160b57cec5SDimitry Andric buf += elementTypeAsString; 16170b57cec5SDimitry Andric buf += ")0);\n\t"; 16180b57cec5SDimitry Andric buf += "}\n"; 16190b57cec5SDimitry Andric 16200b57cec5SDimitry Andric // Insert all these *after* the statement body. 16210b57cec5SDimitry Andric // FIXME: If this should support Obj-C++, support CXXTryStmt 16220b57cec5SDimitry Andric if (isa<CompoundStmt>(S->getBody())) { 16230b57cec5SDimitry Andric SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1); 16240b57cec5SDimitry Andric InsertText(endBodyLoc, buf); 16250b57cec5SDimitry Andric } else { 16260b57cec5SDimitry Andric /* Need to treat single statements specially. For example: 16270b57cec5SDimitry Andric * 16280b57cec5SDimitry Andric * for (A *a in b) if (stuff()) break; 16290b57cec5SDimitry Andric * for (A *a in b) xxxyy; 16300b57cec5SDimitry Andric * 16310b57cec5SDimitry Andric * The following code simply scans ahead to the semi to find the actual end. 16320b57cec5SDimitry Andric */ 16330b57cec5SDimitry Andric const char *stmtBuf = SM->getCharacterData(OrigEnd); 16340b57cec5SDimitry Andric const char *semiBuf = strchr(stmtBuf, ';'); 16350b57cec5SDimitry Andric assert(semiBuf && "Can't find ';'"); 16360b57cec5SDimitry Andric SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1); 16370b57cec5SDimitry Andric InsertText(endBodyLoc, buf); 16380b57cec5SDimitry Andric } 16390b57cec5SDimitry Andric Stmts.pop_back(); 16400b57cec5SDimitry Andric ObjCBcLabelNo.pop_back(); 16410b57cec5SDimitry Andric return nullptr; 16420b57cec5SDimitry Andric } 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric /// RewriteObjCSynchronizedStmt - 16450b57cec5SDimitry Andric /// This routine rewrites @synchronized(expr) stmt; 16460b57cec5SDimitry Andric /// into: 16470b57cec5SDimitry Andric /// objc_sync_enter(expr); 16480b57cec5SDimitry Andric /// @try stmt @finally { objc_sync_exit(expr); } 16490b57cec5SDimitry Andric /// 16500b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 16510b57cec5SDimitry Andric // Get the start location and compute the semi location. 16520b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 16530b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 16540b57cec5SDimitry Andric 16550b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @synchronized location"); 16560b57cec5SDimitry Andric 16570b57cec5SDimitry Andric std::string buf; 16580b57cec5SDimitry Andric buf = "objc_sync_enter((id)"; 16590b57cec5SDimitry Andric const char *lparenBuf = startBuf; 16600b57cec5SDimitry Andric while (*lparenBuf != '(') lparenBuf++; 16610b57cec5SDimitry Andric ReplaceText(startLoc, lparenBuf-startBuf+1, buf); 16620b57cec5SDimitry Andric // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since 16630b57cec5SDimitry Andric // the sync expression is typically a message expression that's already 16640b57cec5SDimitry Andric // been rewritten! (which implies the SourceLocation's are invalid). 16650b57cec5SDimitry Andric SourceLocation endLoc = S->getSynchBody()->getBeginLoc(); 16660b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(endLoc); 16670b57cec5SDimitry Andric while (*endBuf != ')') endBuf--; 16680b57cec5SDimitry Andric SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf); 16690b57cec5SDimitry Andric buf = ");\n"; 16700b57cec5SDimitry Andric // declare a new scope with two variables, _stack and _rethrow. 16710b57cec5SDimitry Andric buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n"; 16720b57cec5SDimitry Andric buf += "int buf[18/*32-bit i386*/];\n"; 16730b57cec5SDimitry Andric buf += "char *pointers[4];} _stack;\n"; 16740b57cec5SDimitry Andric buf += "id volatile _rethrow = 0;\n"; 16750b57cec5SDimitry Andric buf += "objc_exception_try_enter(&_stack);\n"; 16760b57cec5SDimitry Andric buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 16770b57cec5SDimitry Andric ReplaceText(rparenLoc, 1, buf); 16780b57cec5SDimitry Andric startLoc = S->getSynchBody()->getEndLoc(); 16790b57cec5SDimitry Andric startBuf = SM->getCharacterData(startLoc); 16800b57cec5SDimitry Andric 16810b57cec5SDimitry Andric assert((*startBuf == '}') && "bogus @synchronized block"); 16820b57cec5SDimitry Andric SourceLocation lastCurlyLoc = startLoc; 16830b57cec5SDimitry Andric buf = "}\nelse {\n"; 16840b57cec5SDimitry Andric buf += " _rethrow = objc_exception_extract(&_stack);\n"; 16850b57cec5SDimitry Andric buf += "}\n"; 16860b57cec5SDimitry Andric buf += "{ /* implicit finally clause */\n"; 16870b57cec5SDimitry Andric buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 16880b57cec5SDimitry Andric 16890b57cec5SDimitry Andric std::string syncBuf; 16900b57cec5SDimitry Andric syncBuf += " objc_sync_exit("; 16910b57cec5SDimitry Andric 16920b57cec5SDimitry Andric Expr *syncExpr = S->getSynchExpr(); 16930b57cec5SDimitry Andric CastKind CK = syncExpr->getType()->isObjCObjectPointerType() 16940b57cec5SDimitry Andric ? CK_BitCast : 16950b57cec5SDimitry Andric syncExpr->getType()->isBlockPointerType() 16960b57cec5SDimitry Andric ? CK_BlockPointerToObjCPointerCast 16970b57cec5SDimitry Andric : CK_CPointerToObjCPointerCast; 16980b57cec5SDimitry Andric syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 16990b57cec5SDimitry Andric CK, syncExpr); 17000b57cec5SDimitry Andric std::string syncExprBufS; 17010b57cec5SDimitry Andric llvm::raw_string_ostream syncExprBuf(syncExprBufS); 17020b57cec5SDimitry Andric assert(syncExpr != nullptr && "Expected non-null Expr"); 17030b57cec5SDimitry Andric syncExpr->printPretty(syncExprBuf, nullptr, PrintingPolicy(LangOpts)); 17040b57cec5SDimitry Andric syncBuf += syncExprBuf.str(); 17050b57cec5SDimitry Andric syncBuf += ");"; 17060b57cec5SDimitry Andric 17070b57cec5SDimitry Andric buf += syncBuf; 17080b57cec5SDimitry Andric buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n"; 17090b57cec5SDimitry Andric buf += "}\n"; 17100b57cec5SDimitry Andric buf += "}"; 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric ReplaceText(lastCurlyLoc, 1, buf); 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric bool hasReturns = false; 17150b57cec5SDimitry Andric HasReturnStmts(S->getSynchBody(), hasReturns); 17160b57cec5SDimitry Andric if (hasReturns) 17170b57cec5SDimitry Andric RewriteSyncReturnStmts(S->getSynchBody(), syncBuf); 17180b57cec5SDimitry Andric 17190b57cec5SDimitry Andric return nullptr; 17200b57cec5SDimitry Andric } 17210b57cec5SDimitry Andric 17220b57cec5SDimitry Andric void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S) 17230b57cec5SDimitry Andric { 17240b57cec5SDimitry Andric // Perform a bottom up traversal of all children. 17250b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 17260b57cec5SDimitry Andric if (SubStmt) 17270b57cec5SDimitry Andric WarnAboutReturnGotoStmts(SubStmt); 17280b57cec5SDimitry Andric 17290b57cec5SDimitry Andric if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) { 17300b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(S->getBeginLoc()), 17310b57cec5SDimitry Andric TryFinallyContainsReturnDiag); 17320b57cec5SDimitry Andric } 17330b57cec5SDimitry Andric } 17340b57cec5SDimitry Andric 17350b57cec5SDimitry Andric void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns) 17360b57cec5SDimitry Andric { 17370b57cec5SDimitry Andric // Perform a bottom up traversal of all children. 17380b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 17390b57cec5SDimitry Andric if (SubStmt) 17400b57cec5SDimitry Andric HasReturnStmts(SubStmt, hasReturns); 17410b57cec5SDimitry Andric 17420b57cec5SDimitry Andric if (isa<ReturnStmt>(S)) 17430b57cec5SDimitry Andric hasReturns = true; 17440b57cec5SDimitry Andric } 17450b57cec5SDimitry Andric 17460b57cec5SDimitry Andric void RewriteObjC::RewriteTryReturnStmts(Stmt *S) { 17470b57cec5SDimitry Andric // Perform a bottom up traversal of all children. 17480b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 17490b57cec5SDimitry Andric if (SubStmt) { 17500b57cec5SDimitry Andric RewriteTryReturnStmts(SubStmt); 17510b57cec5SDimitry Andric } 17520b57cec5SDimitry Andric if (isa<ReturnStmt>(S)) { 17530b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 17540b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 17550b57cec5SDimitry Andric const char *semiBuf = strchr(startBuf, ';'); 17560b57cec5SDimitry Andric assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'"); 17570b57cec5SDimitry Andric SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 17580b57cec5SDimitry Andric 17590b57cec5SDimitry Andric std::string buf; 17600b57cec5SDimitry Andric buf = "{ objc_exception_try_exit(&_stack); return"; 17610b57cec5SDimitry Andric 17620b57cec5SDimitry Andric ReplaceText(startLoc, 6, buf); 17630b57cec5SDimitry Andric InsertText(onePastSemiLoc, "}"); 17640b57cec5SDimitry Andric } 17650b57cec5SDimitry Andric } 17660b57cec5SDimitry Andric 17670b57cec5SDimitry Andric void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) { 17680b57cec5SDimitry Andric // Perform a bottom up traversal of all children. 17690b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 17700b57cec5SDimitry Andric if (SubStmt) { 17710b57cec5SDimitry Andric RewriteSyncReturnStmts(SubStmt, syncExitBuf); 17720b57cec5SDimitry Andric } 17730b57cec5SDimitry Andric if (isa<ReturnStmt>(S)) { 17740b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 17750b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 17760b57cec5SDimitry Andric 17770b57cec5SDimitry Andric const char *semiBuf = strchr(startBuf, ';'); 17780b57cec5SDimitry Andric assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'"); 17790b57cec5SDimitry Andric SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 17800b57cec5SDimitry Andric 17810b57cec5SDimitry Andric std::string buf; 17820b57cec5SDimitry Andric buf = "{ objc_exception_try_exit(&_stack);"; 17830b57cec5SDimitry Andric buf += syncExitBuf; 17840b57cec5SDimitry Andric buf += " return"; 17850b57cec5SDimitry Andric 17860b57cec5SDimitry Andric ReplaceText(startLoc, 6, buf); 17870b57cec5SDimitry Andric InsertText(onePastSemiLoc, "}"); 17880b57cec5SDimitry Andric } 17890b57cec5SDimitry Andric } 17900b57cec5SDimitry Andric 17910b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { 17920b57cec5SDimitry Andric // Get the start location and compute the semi location. 17930b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 17940b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 17950b57cec5SDimitry Andric 17960b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @try location"); 17970b57cec5SDimitry Andric 17980b57cec5SDimitry Andric std::string buf; 17990b57cec5SDimitry Andric // declare a new scope with two variables, _stack and _rethrow. 18000b57cec5SDimitry Andric buf = "/* @try scope begin */ { struct _objc_exception_data {\n"; 18010b57cec5SDimitry Andric buf += "int buf[18/*32-bit i386*/];\n"; 18020b57cec5SDimitry Andric buf += "char *pointers[4];} _stack;\n"; 18030b57cec5SDimitry Andric buf += "id volatile _rethrow = 0;\n"; 18040b57cec5SDimitry Andric buf += "objc_exception_try_enter(&_stack);\n"; 18050b57cec5SDimitry Andric buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 18060b57cec5SDimitry Andric 18070b57cec5SDimitry Andric ReplaceText(startLoc, 4, buf); 18080b57cec5SDimitry Andric 18090b57cec5SDimitry Andric startLoc = S->getTryBody()->getEndLoc(); 18100b57cec5SDimitry Andric startBuf = SM->getCharacterData(startLoc); 18110b57cec5SDimitry Andric 18120b57cec5SDimitry Andric assert((*startBuf == '}') && "bogus @try block"); 18130b57cec5SDimitry Andric 18140b57cec5SDimitry Andric SourceLocation lastCurlyLoc = startLoc; 18150b57cec5SDimitry Andric if (S->getNumCatchStmts()) { 18160b57cec5SDimitry Andric startLoc = startLoc.getLocWithOffset(1); 18170b57cec5SDimitry Andric buf = " /* @catch begin */ else {\n"; 18180b57cec5SDimitry Andric buf += " id _caught = objc_exception_extract(&_stack);\n"; 18190b57cec5SDimitry Andric buf += " objc_exception_try_enter (&_stack);\n"; 18200b57cec5SDimitry Andric buf += " if (_setjmp(_stack.buf))\n"; 18210b57cec5SDimitry Andric buf += " _rethrow = objc_exception_extract(&_stack);\n"; 18220b57cec5SDimitry Andric buf += " else { /* @catch continue */"; 18230b57cec5SDimitry Andric 18240b57cec5SDimitry Andric InsertText(startLoc, buf); 18250b57cec5SDimitry Andric } else { /* no catch list */ 18260b57cec5SDimitry Andric buf = "}\nelse {\n"; 18270b57cec5SDimitry Andric buf += " _rethrow = objc_exception_extract(&_stack);\n"; 18280b57cec5SDimitry Andric buf += "}"; 18290b57cec5SDimitry Andric ReplaceText(lastCurlyLoc, 1, buf); 18300b57cec5SDimitry Andric } 18310b57cec5SDimitry Andric Stmt *lastCatchBody = nullptr; 18320b57cec5SDimitry Andric for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { 18330b57cec5SDimitry Andric ObjCAtCatchStmt *Catch = S->getCatchStmt(I); 18340b57cec5SDimitry Andric VarDecl *catchDecl = Catch->getCatchParamDecl(); 18350b57cec5SDimitry Andric 18360b57cec5SDimitry Andric if (I == 0) 18370b57cec5SDimitry Andric buf = "if ("; // we are generating code for the first catch clause 18380b57cec5SDimitry Andric else 18390b57cec5SDimitry Andric buf = "else if ("; 18400b57cec5SDimitry Andric startLoc = Catch->getBeginLoc(); 18410b57cec5SDimitry Andric startBuf = SM->getCharacterData(startLoc); 18420b57cec5SDimitry Andric 18430b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @catch location"); 18440b57cec5SDimitry Andric 18450b57cec5SDimitry Andric const char *lParenLoc = strchr(startBuf, '('); 18460b57cec5SDimitry Andric 18470b57cec5SDimitry Andric if (Catch->hasEllipsis()) { 18480b57cec5SDimitry Andric // Now rewrite the body... 18490b57cec5SDimitry Andric lastCatchBody = Catch->getCatchBody(); 18500b57cec5SDimitry Andric SourceLocation bodyLoc = lastCatchBody->getBeginLoc(); 18510b57cec5SDimitry Andric const char *bodyBuf = SM->getCharacterData(bodyLoc); 18520b57cec5SDimitry Andric assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' && 18530b57cec5SDimitry Andric "bogus @catch paren location"); 18540b57cec5SDimitry Andric assert((*bodyBuf == '{') && "bogus @catch body location"); 18550b57cec5SDimitry Andric 18560b57cec5SDimitry Andric buf += "1) { id _tmp = _caught;"; 18570b57cec5SDimitry Andric Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf); 18580b57cec5SDimitry Andric } else if (catchDecl) { 18590b57cec5SDimitry Andric QualType t = catchDecl->getType(); 18600b57cec5SDimitry Andric if (t == Context->getObjCIdType()) { 18610b57cec5SDimitry Andric buf += "1) { "; 18620b57cec5SDimitry Andric ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 18630b57cec5SDimitry Andric } else if (const ObjCObjectPointerType *Ptr = 18640b57cec5SDimitry Andric t->getAs<ObjCObjectPointerType>()) { 18650b57cec5SDimitry Andric // Should be a pointer to a class. 18660b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface(); 18670b57cec5SDimitry Andric if (IDecl) { 18680b57cec5SDimitry Andric buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; 18690b57cec5SDimitry Andric buf += IDecl->getNameAsString(); 18700b57cec5SDimitry Andric buf += "\"), (struct objc_object *)_caught)) { "; 18710b57cec5SDimitry Andric ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 18720b57cec5SDimitry Andric } 18730b57cec5SDimitry Andric } 18740b57cec5SDimitry Andric // Now rewrite the body... 18750b57cec5SDimitry Andric lastCatchBody = Catch->getCatchBody(); 18760b57cec5SDimitry Andric SourceLocation rParenLoc = Catch->getRParenLoc(); 18770b57cec5SDimitry Andric SourceLocation bodyLoc = lastCatchBody->getBeginLoc(); 18780b57cec5SDimitry Andric const char *bodyBuf = SM->getCharacterData(bodyLoc); 18790b57cec5SDimitry Andric const char *rParenBuf = SM->getCharacterData(rParenLoc); 18800b57cec5SDimitry Andric assert((*rParenBuf == ')') && "bogus @catch paren location"); 18810b57cec5SDimitry Andric assert((*bodyBuf == '{') && "bogus @catch body location"); 18820b57cec5SDimitry Andric 18830b57cec5SDimitry Andric // Here we replace ") {" with "= _caught;" (which initializes and 18840b57cec5SDimitry Andric // declares the @catch parameter). 18850b57cec5SDimitry Andric ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;"); 18860b57cec5SDimitry Andric } else { 18870b57cec5SDimitry Andric llvm_unreachable("@catch rewrite bug"); 18880b57cec5SDimitry Andric } 18890b57cec5SDimitry Andric } 18900b57cec5SDimitry Andric // Complete the catch list... 18910b57cec5SDimitry Andric if (lastCatchBody) { 18920b57cec5SDimitry Andric SourceLocation bodyLoc = lastCatchBody->getEndLoc(); 18930b57cec5SDimitry Andric assert(*SM->getCharacterData(bodyLoc) == '}' && 18940b57cec5SDimitry Andric "bogus @catch body location"); 18950b57cec5SDimitry Andric 18960b57cec5SDimitry Andric // Insert the last (implicit) else clause *before* the right curly brace. 18970b57cec5SDimitry Andric bodyLoc = bodyLoc.getLocWithOffset(-1); 18980b57cec5SDimitry Andric buf = "} /* last catch end */\n"; 18990b57cec5SDimitry Andric buf += "else {\n"; 19000b57cec5SDimitry Andric buf += " _rethrow = _caught;\n"; 19010b57cec5SDimitry Andric buf += " objc_exception_try_exit(&_stack);\n"; 19020b57cec5SDimitry Andric buf += "} } /* @catch end */\n"; 19030b57cec5SDimitry Andric if (!S->getFinallyStmt()) 19040b57cec5SDimitry Andric buf += "}\n"; 19050b57cec5SDimitry Andric InsertText(bodyLoc, buf); 19060b57cec5SDimitry Andric 19070b57cec5SDimitry Andric // Set lastCurlyLoc 19080b57cec5SDimitry Andric lastCurlyLoc = lastCatchBody->getEndLoc(); 19090b57cec5SDimitry Andric } 19100b57cec5SDimitry Andric if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) { 19110b57cec5SDimitry Andric startLoc = finalStmt->getBeginLoc(); 19120b57cec5SDimitry Andric startBuf = SM->getCharacterData(startLoc); 19130b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @finally start"); 19140b57cec5SDimitry Andric 19150b57cec5SDimitry Andric ReplaceText(startLoc, 8, "/* @finally */"); 19160b57cec5SDimitry Andric 19170b57cec5SDimitry Andric Stmt *body = finalStmt->getFinallyBody(); 19180b57cec5SDimitry Andric SourceLocation startLoc = body->getBeginLoc(); 19190b57cec5SDimitry Andric SourceLocation endLoc = body->getEndLoc(); 19200b57cec5SDimitry Andric assert(*SM->getCharacterData(startLoc) == '{' && 19210b57cec5SDimitry Andric "bogus @finally body location"); 19220b57cec5SDimitry Andric assert(*SM->getCharacterData(endLoc) == '}' && 19230b57cec5SDimitry Andric "bogus @finally body location"); 19240b57cec5SDimitry Andric 19250b57cec5SDimitry Andric startLoc = startLoc.getLocWithOffset(1); 19260b57cec5SDimitry Andric InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n"); 19270b57cec5SDimitry Andric endLoc = endLoc.getLocWithOffset(-1); 19280b57cec5SDimitry Andric InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n"); 19290b57cec5SDimitry Andric 19300b57cec5SDimitry Andric // Set lastCurlyLoc 19310b57cec5SDimitry Andric lastCurlyLoc = body->getEndLoc(); 19320b57cec5SDimitry Andric 19330b57cec5SDimitry Andric // Now check for any return/continue/go statements within the @try. 19340b57cec5SDimitry Andric WarnAboutReturnGotoStmts(S->getTryBody()); 19350b57cec5SDimitry Andric } else { /* no finally clause - make sure we synthesize an implicit one */ 19360b57cec5SDimitry Andric buf = "{ /* implicit finally clause */\n"; 19370b57cec5SDimitry Andric buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 19380b57cec5SDimitry Andric buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; 19390b57cec5SDimitry Andric buf += "}"; 19400b57cec5SDimitry Andric ReplaceText(lastCurlyLoc, 1, buf); 19410b57cec5SDimitry Andric 19420b57cec5SDimitry Andric // Now check for any return/continue/go statements within the @try. 19430b57cec5SDimitry Andric // The implicit finally clause won't called if the @try contains any 19440b57cec5SDimitry Andric // jump statements. 19450b57cec5SDimitry Andric bool hasReturns = false; 19460b57cec5SDimitry Andric HasReturnStmts(S->getTryBody(), hasReturns); 19470b57cec5SDimitry Andric if (hasReturns) 19480b57cec5SDimitry Andric RewriteTryReturnStmts(S->getTryBody()); 19490b57cec5SDimitry Andric } 19500b57cec5SDimitry Andric // Now emit the final closing curly brace... 19510b57cec5SDimitry Andric lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1); 19520b57cec5SDimitry Andric InsertText(lastCurlyLoc, " } /* @try scope end */\n"); 19530b57cec5SDimitry Andric return nullptr; 19540b57cec5SDimitry Andric } 19550b57cec5SDimitry Andric 19560b57cec5SDimitry Andric // This can't be done with ReplaceStmt(S, ThrowExpr), since 19570b57cec5SDimitry Andric // the throw expression is typically a message expression that's already 19580b57cec5SDimitry Andric // been rewritten! (which implies the SourceLocation's are invalid). 19590b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { 19600b57cec5SDimitry Andric // Get the start location and compute the semi location. 19610b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 19620b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 19630b57cec5SDimitry Andric 19640b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @throw location"); 19650b57cec5SDimitry Andric 19660b57cec5SDimitry Andric std::string buf; 19670b57cec5SDimitry Andric /* void objc_exception_throw(id) __attribute__((noreturn)); */ 19680b57cec5SDimitry Andric if (S->getThrowExpr()) 19690b57cec5SDimitry Andric buf = "objc_exception_throw("; 19700b57cec5SDimitry Andric else // add an implicit argument 19710b57cec5SDimitry Andric buf = "objc_exception_throw(_caught"; 19720b57cec5SDimitry Andric 19730b57cec5SDimitry Andric // handle "@ throw" correctly. 19740b57cec5SDimitry Andric const char *wBuf = strchr(startBuf, 'w'); 19750b57cec5SDimitry Andric assert((*wBuf == 'w') && "@throw: can't find 'w'"); 19760b57cec5SDimitry Andric ReplaceText(startLoc, wBuf-startBuf+1, buf); 19770b57cec5SDimitry Andric 19780b57cec5SDimitry Andric const char *semiBuf = strchr(startBuf, ';'); 19790b57cec5SDimitry Andric assert((*semiBuf == ';') && "@throw: can't find ';'"); 19800b57cec5SDimitry Andric SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf); 19810b57cec5SDimitry Andric ReplaceText(semiLoc, 1, ");"); 19820b57cec5SDimitry Andric return nullptr; 19830b57cec5SDimitry Andric } 19840b57cec5SDimitry Andric 19850b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { 19860b57cec5SDimitry Andric // Create a new string expression. 19870b57cec5SDimitry Andric std::string StrEncoding; 19880b57cec5SDimitry Andric Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); 19890b57cec5SDimitry Andric Expr *Replacement = getStringLiteral(StrEncoding); 19900b57cec5SDimitry Andric ReplaceStmt(Exp, Replacement); 19910b57cec5SDimitry Andric 19920b57cec5SDimitry Andric // Replace this subexpr in the parent. 19930b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 19940b57cec5SDimitry Andric return Replacement; 19950b57cec5SDimitry Andric } 19960b57cec5SDimitry Andric 19970b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { 19980b57cec5SDimitry Andric if (!SelGetUidFunctionDecl) 19990b57cec5SDimitry Andric SynthSelGetUidFunctionDecl(); 20000b57cec5SDimitry Andric assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl"); 20010b57cec5SDimitry Andric // Create a call to sel_registerName("selName"). 20020b57cec5SDimitry Andric SmallVector<Expr*, 8> SelExprs; 20030b57cec5SDimitry Andric SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString())); 20040b57cec5SDimitry Andric CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 20050b57cec5SDimitry Andric SelExprs); 20060b57cec5SDimitry Andric ReplaceStmt(Exp, SelExp); 20070b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 20080b57cec5SDimitry Andric return SelExp; 20090b57cec5SDimitry Andric } 20100b57cec5SDimitry Andric 20110b57cec5SDimitry Andric CallExpr * 20120b57cec5SDimitry Andric RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD, 20130b57cec5SDimitry Andric ArrayRef<Expr *> Args, 20140b57cec5SDimitry Andric SourceLocation StartLoc, 20150b57cec5SDimitry Andric SourceLocation EndLoc) { 20160b57cec5SDimitry Andric // Get the type, we will need to reference it in a couple spots. 20170b57cec5SDimitry Andric QualType msgSendType = FD->getType(); 20180b57cec5SDimitry Andric 20190b57cec5SDimitry Andric // Create a reference to the objc_msgSend() declaration. 20200b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType, 20210b57cec5SDimitry Andric VK_LValue, SourceLocation()); 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric // Now, we cast the reference to a pointer to the objc_msgSend type. 20240b57cec5SDimitry Andric QualType pToFunc = Context->getPointerType(msgSendType); 20250b57cec5SDimitry Andric ImplicitCastExpr *ICE = 20260b57cec5SDimitry Andric ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, 2027fe6060f1SDimitry Andric DRE, nullptr, VK_PRValue, FPOptionsOverride()); 20280b57cec5SDimitry Andric 2029a7dea167SDimitry Andric const auto *FT = msgSendType->castAs<FunctionType>(); 20300b57cec5SDimitry Andric 2031e8d8bef9SDimitry Andric CallExpr *Exp = 2032e8d8bef9SDimitry Andric CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context), 2033fe6060f1SDimitry Andric VK_PRValue, EndLoc, FPOptionsOverride()); 20340b57cec5SDimitry Andric return Exp; 20350b57cec5SDimitry Andric } 20360b57cec5SDimitry Andric 20370b57cec5SDimitry Andric static bool scanForProtocolRefs(const char *startBuf, const char *endBuf, 20380b57cec5SDimitry Andric const char *&startRef, const char *&endRef) { 20390b57cec5SDimitry Andric while (startBuf < endBuf) { 20400b57cec5SDimitry Andric if (*startBuf == '<') 20410b57cec5SDimitry Andric startRef = startBuf; // mark the start. 20420b57cec5SDimitry Andric if (*startBuf == '>') { 20430b57cec5SDimitry Andric if (startRef && *startRef == '<') { 20440b57cec5SDimitry Andric endRef = startBuf; // mark the end. 20450b57cec5SDimitry Andric return true; 20460b57cec5SDimitry Andric } 20470b57cec5SDimitry Andric return false; 20480b57cec5SDimitry Andric } 20490b57cec5SDimitry Andric startBuf++; 20500b57cec5SDimitry Andric } 20510b57cec5SDimitry Andric return false; 20520b57cec5SDimitry Andric } 20530b57cec5SDimitry Andric 20540b57cec5SDimitry Andric static void scanToNextArgument(const char *&argRef) { 20550b57cec5SDimitry Andric int angle = 0; 20560b57cec5SDimitry Andric while (*argRef != ')' && (*argRef != ',' || angle > 0)) { 20570b57cec5SDimitry Andric if (*argRef == '<') 20580b57cec5SDimitry Andric angle++; 20590b57cec5SDimitry Andric else if (*argRef == '>') 20600b57cec5SDimitry Andric angle--; 20610b57cec5SDimitry Andric argRef++; 20620b57cec5SDimitry Andric } 20630b57cec5SDimitry Andric assert(angle == 0 && "scanToNextArgument - bad protocol type syntax"); 20640b57cec5SDimitry Andric } 20650b57cec5SDimitry Andric 20660b57cec5SDimitry Andric bool RewriteObjC::needToScanForQualifiers(QualType T) { 20670b57cec5SDimitry Andric if (T->isObjCQualifiedIdType()) 20680b57cec5SDimitry Andric return true; 20690b57cec5SDimitry Andric if (const PointerType *PT = T->getAs<PointerType>()) { 20700b57cec5SDimitry Andric if (PT->getPointeeType()->isObjCQualifiedIdType()) 20710b57cec5SDimitry Andric return true; 20720b57cec5SDimitry Andric } 20730b57cec5SDimitry Andric if (T->isObjCObjectPointerType()) { 20740b57cec5SDimitry Andric T = T->getPointeeType(); 20750b57cec5SDimitry Andric return T->isObjCQualifiedInterfaceType(); 20760b57cec5SDimitry Andric } 20770b57cec5SDimitry Andric if (T->isArrayType()) { 20780b57cec5SDimitry Andric QualType ElemTy = Context->getBaseElementType(T); 20790b57cec5SDimitry Andric return needToScanForQualifiers(ElemTy); 20800b57cec5SDimitry Andric } 20810b57cec5SDimitry Andric return false; 20820b57cec5SDimitry Andric } 20830b57cec5SDimitry Andric 20840b57cec5SDimitry Andric void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { 20850b57cec5SDimitry Andric QualType Type = E->getType(); 20860b57cec5SDimitry Andric if (needToScanForQualifiers(Type)) { 20870b57cec5SDimitry Andric SourceLocation Loc, EndLoc; 20880b57cec5SDimitry Andric 20890b57cec5SDimitry Andric if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { 20900b57cec5SDimitry Andric Loc = ECE->getLParenLoc(); 20910b57cec5SDimitry Andric EndLoc = ECE->getRParenLoc(); 20920b57cec5SDimitry Andric } else { 20930b57cec5SDimitry Andric Loc = E->getBeginLoc(); 20940b57cec5SDimitry Andric EndLoc = E->getEndLoc(); 20950b57cec5SDimitry Andric } 20960b57cec5SDimitry Andric // This will defend against trying to rewrite synthesized expressions. 20970b57cec5SDimitry Andric if (Loc.isInvalid() || EndLoc.isInvalid()) 20980b57cec5SDimitry Andric return; 20990b57cec5SDimitry Andric 21000b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(Loc); 21010b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(EndLoc); 21020b57cec5SDimitry Andric const char *startRef = nullptr, *endRef = nullptr; 21030b57cec5SDimitry Andric if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 21040b57cec5SDimitry Andric // Get the locations of the startRef, endRef. 21050b57cec5SDimitry Andric SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf); 21060b57cec5SDimitry Andric SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1); 21070b57cec5SDimitry Andric // Comment out the protocol references. 21080b57cec5SDimitry Andric InsertText(LessLoc, "/*"); 21090b57cec5SDimitry Andric InsertText(GreaterLoc, "*/"); 21100b57cec5SDimitry Andric } 21110b57cec5SDimitry Andric } 21120b57cec5SDimitry Andric } 21130b57cec5SDimitry Andric 21140b57cec5SDimitry Andric void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { 21150b57cec5SDimitry Andric SourceLocation Loc; 21160b57cec5SDimitry Andric QualType Type; 21170b57cec5SDimitry Andric const FunctionProtoType *proto = nullptr; 21180b57cec5SDimitry Andric if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) { 21190b57cec5SDimitry Andric Loc = VD->getLocation(); 21200b57cec5SDimitry Andric Type = VD->getType(); 21210b57cec5SDimitry Andric } 21220b57cec5SDimitry Andric else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) { 21230b57cec5SDimitry Andric Loc = FD->getLocation(); 21240b57cec5SDimitry Andric // Check for ObjC 'id' and class types that have been adorned with protocol 21250b57cec5SDimitry Andric // information (id<p>, C<p>*). The protocol references need to be rewritten! 21260b57cec5SDimitry Andric const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 21270b57cec5SDimitry Andric assert(funcType && "missing function type"); 21280b57cec5SDimitry Andric proto = dyn_cast<FunctionProtoType>(funcType); 21290b57cec5SDimitry Andric if (!proto) 21300b57cec5SDimitry Andric return; 21310b57cec5SDimitry Andric Type = proto->getReturnType(); 21320b57cec5SDimitry Andric } 21330b57cec5SDimitry Andric else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) { 21340b57cec5SDimitry Andric Loc = FD->getLocation(); 21350b57cec5SDimitry Andric Type = FD->getType(); 21360b57cec5SDimitry Andric } 21370b57cec5SDimitry Andric else 21380b57cec5SDimitry Andric return; 21390b57cec5SDimitry Andric 21400b57cec5SDimitry Andric if (needToScanForQualifiers(Type)) { 21410b57cec5SDimitry Andric // Since types are unique, we need to scan the buffer. 21420b57cec5SDimitry Andric 21430b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(Loc); 21440b57cec5SDimitry Andric const char *startBuf = endBuf; 21450b57cec5SDimitry Andric while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) 21460b57cec5SDimitry Andric startBuf--; // scan backward (from the decl location) for return type. 21470b57cec5SDimitry Andric const char *startRef = nullptr, *endRef = nullptr; 21480b57cec5SDimitry Andric if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 21490b57cec5SDimitry Andric // Get the locations of the startRef, endRef. 21500b57cec5SDimitry Andric SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf); 21510b57cec5SDimitry Andric SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1); 21520b57cec5SDimitry Andric // Comment out the protocol references. 21530b57cec5SDimitry Andric InsertText(LessLoc, "/*"); 21540b57cec5SDimitry Andric InsertText(GreaterLoc, "*/"); 21550b57cec5SDimitry Andric } 21560b57cec5SDimitry Andric } 21570b57cec5SDimitry Andric if (!proto) 21580b57cec5SDimitry Andric return; // most likely, was a variable 21590b57cec5SDimitry Andric // Now check arguments. 21600b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(Loc); 21610b57cec5SDimitry Andric const char *startFuncBuf = startBuf; 21620b57cec5SDimitry Andric for (unsigned i = 0; i < proto->getNumParams(); i++) { 21630b57cec5SDimitry Andric if (needToScanForQualifiers(proto->getParamType(i))) { 21640b57cec5SDimitry Andric // Since types are unique, we need to scan the buffer. 21650b57cec5SDimitry Andric 21660b57cec5SDimitry Andric const char *endBuf = startBuf; 21670b57cec5SDimitry Andric // scan forward (from the decl location) for argument types. 21680b57cec5SDimitry Andric scanToNextArgument(endBuf); 21690b57cec5SDimitry Andric const char *startRef = nullptr, *endRef = nullptr; 21700b57cec5SDimitry Andric if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 21710b57cec5SDimitry Andric // Get the locations of the startRef, endRef. 21720b57cec5SDimitry Andric SourceLocation LessLoc = 21730b57cec5SDimitry Andric Loc.getLocWithOffset(startRef-startFuncBuf); 21740b57cec5SDimitry Andric SourceLocation GreaterLoc = 21750b57cec5SDimitry Andric Loc.getLocWithOffset(endRef-startFuncBuf+1); 21760b57cec5SDimitry Andric // Comment out the protocol references. 21770b57cec5SDimitry Andric InsertText(LessLoc, "/*"); 21780b57cec5SDimitry Andric InsertText(GreaterLoc, "*/"); 21790b57cec5SDimitry Andric } 21800b57cec5SDimitry Andric startBuf = ++endBuf; 21810b57cec5SDimitry Andric } 21820b57cec5SDimitry Andric else { 21830b57cec5SDimitry Andric // If the function name is derived from a macro expansion, then the 21840b57cec5SDimitry Andric // argument buffer will not follow the name. Need to speak with Chris. 21850b57cec5SDimitry Andric while (*startBuf && *startBuf != ')' && *startBuf != ',') 21860b57cec5SDimitry Andric startBuf++; // scan forward (from the decl location) for argument types. 21870b57cec5SDimitry Andric startBuf++; 21880b57cec5SDimitry Andric } 21890b57cec5SDimitry Andric } 21900b57cec5SDimitry Andric } 21910b57cec5SDimitry Andric 21920b57cec5SDimitry Andric void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) { 21930b57cec5SDimitry Andric QualType QT = ND->getType(); 21940b57cec5SDimitry Andric const Type* TypePtr = QT->getAs<Type>(); 21950b57cec5SDimitry Andric if (!isa<TypeOfExprType>(TypePtr)) 21960b57cec5SDimitry Andric return; 21970b57cec5SDimitry Andric while (isa<TypeOfExprType>(TypePtr)) { 21980b57cec5SDimitry Andric const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 21990b57cec5SDimitry Andric QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 22000b57cec5SDimitry Andric TypePtr = QT->getAs<Type>(); 22010b57cec5SDimitry Andric } 22020b57cec5SDimitry Andric // FIXME. This will not work for multiple declarators; as in: 22030b57cec5SDimitry Andric // __typeof__(a) b,c,d; 22040b57cec5SDimitry Andric std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy())); 22050b57cec5SDimitry Andric SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 22060b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(DeclLoc); 22070b57cec5SDimitry Andric if (ND->getInit()) { 22080b57cec5SDimitry Andric std::string Name(ND->getNameAsString()); 22090b57cec5SDimitry Andric TypeAsString += " " + Name + " = "; 22100b57cec5SDimitry Andric Expr *E = ND->getInit(); 22110b57cec5SDimitry Andric SourceLocation startLoc; 22120b57cec5SDimitry Andric if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 22130b57cec5SDimitry Andric startLoc = ECE->getLParenLoc(); 22140b57cec5SDimitry Andric else 22150b57cec5SDimitry Andric startLoc = E->getBeginLoc(); 22160b57cec5SDimitry Andric startLoc = SM->getExpansionLoc(startLoc); 22170b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(startLoc); 22180b57cec5SDimitry Andric ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 22190b57cec5SDimitry Andric } 22200b57cec5SDimitry Andric else { 22210b57cec5SDimitry Andric SourceLocation X = ND->getEndLoc(); 22220b57cec5SDimitry Andric X = SM->getExpansionLoc(X); 22230b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(X); 22240b57cec5SDimitry Andric ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 22250b57cec5SDimitry Andric } 22260b57cec5SDimitry Andric } 22270b57cec5SDimitry Andric 22280b57cec5SDimitry Andric // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); 22290b57cec5SDimitry Andric void RewriteObjC::SynthSelGetUidFunctionDecl() { 22300b57cec5SDimitry Andric IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); 22310b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 22320b57cec5SDimitry Andric ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 22330b57cec5SDimitry Andric QualType getFuncType = 22340b57cec5SDimitry Andric getSimpleFunctionType(Context->getObjCSelType(), ArgTys); 22350b57cec5SDimitry Andric SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 22360b57cec5SDimitry Andric SourceLocation(), 22370b57cec5SDimitry Andric SourceLocation(), 22380b57cec5SDimitry Andric SelGetUidIdent, getFuncType, 22390b57cec5SDimitry Andric nullptr, SC_Extern); 22400b57cec5SDimitry Andric } 22410b57cec5SDimitry Andric 22420b57cec5SDimitry Andric void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { 22430b57cec5SDimitry Andric // declared in <objc/objc.h> 22440b57cec5SDimitry Andric if (FD->getIdentifier() && 22450b57cec5SDimitry Andric FD->getName() == "sel_registerName") { 22460b57cec5SDimitry Andric SelGetUidFunctionDecl = FD; 22470b57cec5SDimitry Andric return; 22480b57cec5SDimitry Andric } 22490b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(FD); 22500b57cec5SDimitry Andric } 22510b57cec5SDimitry Andric 22520b57cec5SDimitry Andric void RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) { 22530b57cec5SDimitry Andric std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 22540b57cec5SDimitry Andric const char *argPtr = TypeString.c_str(); 22550b57cec5SDimitry Andric if (!strchr(argPtr, '^')) { 22560b57cec5SDimitry Andric Str += TypeString; 22570b57cec5SDimitry Andric return; 22580b57cec5SDimitry Andric } 22590b57cec5SDimitry Andric while (*argPtr) { 22600b57cec5SDimitry Andric Str += (*argPtr == '^' ? '*' : *argPtr); 22610b57cec5SDimitry Andric argPtr++; 22620b57cec5SDimitry Andric } 22630b57cec5SDimitry Andric } 22640b57cec5SDimitry Andric 22650b57cec5SDimitry Andric // FIXME. Consolidate this routine with RewriteBlockPointerType. 22660b57cec5SDimitry Andric void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str, 22670b57cec5SDimitry Andric ValueDecl *VD) { 22680b57cec5SDimitry Andric QualType Type = VD->getType(); 22690b57cec5SDimitry Andric std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 22700b57cec5SDimitry Andric const char *argPtr = TypeString.c_str(); 22710b57cec5SDimitry Andric int paren = 0; 22720b57cec5SDimitry Andric while (*argPtr) { 22730b57cec5SDimitry Andric switch (*argPtr) { 22740b57cec5SDimitry Andric case '(': 22750b57cec5SDimitry Andric Str += *argPtr; 22760b57cec5SDimitry Andric paren++; 22770b57cec5SDimitry Andric break; 22780b57cec5SDimitry Andric case ')': 22790b57cec5SDimitry Andric Str += *argPtr; 22800b57cec5SDimitry Andric paren--; 22810b57cec5SDimitry Andric break; 22820b57cec5SDimitry Andric case '^': 22830b57cec5SDimitry Andric Str += '*'; 22840b57cec5SDimitry Andric if (paren == 1) 22850b57cec5SDimitry Andric Str += VD->getNameAsString(); 22860b57cec5SDimitry Andric break; 22870b57cec5SDimitry Andric default: 22880b57cec5SDimitry Andric Str += *argPtr; 22890b57cec5SDimitry Andric break; 22900b57cec5SDimitry Andric } 22910b57cec5SDimitry Andric argPtr++; 22920b57cec5SDimitry Andric } 22930b57cec5SDimitry Andric } 22940b57cec5SDimitry Andric 22950b57cec5SDimitry Andric void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { 22960b57cec5SDimitry Andric SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 22970b57cec5SDimitry Andric const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 2298a7dea167SDimitry Andric const FunctionProtoType *proto = dyn_cast_or_null<FunctionProtoType>(funcType); 22990b57cec5SDimitry Andric if (!proto) 23000b57cec5SDimitry Andric return; 23010b57cec5SDimitry Andric QualType Type = proto->getReturnType(); 23020b57cec5SDimitry Andric std::string FdStr = Type.getAsString(Context->getPrintingPolicy()); 23030b57cec5SDimitry Andric FdStr += " "; 23040b57cec5SDimitry Andric FdStr += FD->getName(); 23050b57cec5SDimitry Andric FdStr += "("; 23060b57cec5SDimitry Andric unsigned numArgs = proto->getNumParams(); 23070b57cec5SDimitry Andric for (unsigned i = 0; i < numArgs; i++) { 23080b57cec5SDimitry Andric QualType ArgType = proto->getParamType(i); 23090b57cec5SDimitry Andric RewriteBlockPointerType(FdStr, ArgType); 23100b57cec5SDimitry Andric if (i+1 < numArgs) 23110b57cec5SDimitry Andric FdStr += ", "; 23120b57cec5SDimitry Andric } 23130b57cec5SDimitry Andric FdStr += ");\n"; 23140b57cec5SDimitry Andric InsertText(FunLocStart, FdStr); 23150b57cec5SDimitry Andric CurFunctionDeclToDeclareForBlock = nullptr; 23160b57cec5SDimitry Andric } 23170b57cec5SDimitry Andric 23180b57cec5SDimitry Andric // SynthSuperConstructorFunctionDecl - id objc_super(id obj, id super); 23190b57cec5SDimitry Andric void RewriteObjC::SynthSuperConstructorFunctionDecl() { 23200b57cec5SDimitry Andric if (SuperConstructorFunctionDecl) 23210b57cec5SDimitry Andric return; 23220b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super"); 23230b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 23240b57cec5SDimitry Andric QualType argT = Context->getObjCIdType(); 23250b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'id' type"); 23260b57cec5SDimitry Andric ArgTys.push_back(argT); 23270b57cec5SDimitry Andric ArgTys.push_back(argT); 23280b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 23290b57cec5SDimitry Andric ArgTys); 23300b57cec5SDimitry Andric SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 23310b57cec5SDimitry Andric SourceLocation(), 23320b57cec5SDimitry Andric SourceLocation(), 23330b57cec5SDimitry Andric msgSendIdent, msgSendType, 23340b57cec5SDimitry Andric nullptr, SC_Extern); 23350b57cec5SDimitry Andric } 23360b57cec5SDimitry Andric 23370b57cec5SDimitry Andric // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); 23380b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendFunctionDecl() { 23390b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend"); 23400b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 23410b57cec5SDimitry Andric QualType argT = Context->getObjCIdType(); 23420b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'id' type"); 23430b57cec5SDimitry Andric ArgTys.push_back(argT); 23440b57cec5SDimitry Andric argT = Context->getObjCSelType(); 23450b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'SEL' type"); 23460b57cec5SDimitry Andric ArgTys.push_back(argT); 23470b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 23480b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 23490b57cec5SDimitry Andric MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 23500b57cec5SDimitry Andric SourceLocation(), 23510b57cec5SDimitry Andric SourceLocation(), 23520b57cec5SDimitry Andric msgSendIdent, msgSendType, 23530b57cec5SDimitry Andric nullptr, SC_Extern); 23540b57cec5SDimitry Andric } 23550b57cec5SDimitry Andric 23560b57cec5SDimitry Andric // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...); 23570b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendSuperFunctionDecl() { 23580b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); 23590b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 2360*5f757f3fSDimitry Andric RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 23610b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 23620b57cec5SDimitry Andric &Context->Idents.get("objc_super")); 23630b57cec5SDimitry Andric QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 23640b57cec5SDimitry Andric assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 23650b57cec5SDimitry Andric ArgTys.push_back(argT); 23660b57cec5SDimitry Andric argT = Context->getObjCSelType(); 23670b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'SEL' type"); 23680b57cec5SDimitry Andric ArgTys.push_back(argT); 23690b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 23700b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 23710b57cec5SDimitry Andric MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 23720b57cec5SDimitry Andric SourceLocation(), 23730b57cec5SDimitry Andric SourceLocation(), 23740b57cec5SDimitry Andric msgSendIdent, msgSendType, 23750b57cec5SDimitry Andric nullptr, SC_Extern); 23760b57cec5SDimitry Andric } 23770b57cec5SDimitry Andric 23780b57cec5SDimitry Andric // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); 23790b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendStretFunctionDecl() { 23800b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret"); 23810b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 23820b57cec5SDimitry Andric QualType argT = Context->getObjCIdType(); 23830b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'id' type"); 23840b57cec5SDimitry Andric ArgTys.push_back(argT); 23850b57cec5SDimitry Andric argT = Context->getObjCSelType(); 23860b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'SEL' type"); 23870b57cec5SDimitry Andric ArgTys.push_back(argT); 23880b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 23890b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 23900b57cec5SDimitry Andric MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 23910b57cec5SDimitry Andric SourceLocation(), 23920b57cec5SDimitry Andric SourceLocation(), 23930b57cec5SDimitry Andric msgSendIdent, msgSendType, 23940b57cec5SDimitry Andric nullptr, SC_Extern); 23950b57cec5SDimitry Andric } 23960b57cec5SDimitry Andric 23970b57cec5SDimitry Andric // SynthMsgSendSuperStretFunctionDecl - 23980b57cec5SDimitry Andric // id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...); 23990b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { 24000b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = 24010b57cec5SDimitry Andric &Context->Idents.get("objc_msgSendSuper_stret"); 24020b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 2403*5f757f3fSDimitry Andric RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 24040b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 24050b57cec5SDimitry Andric &Context->Idents.get("objc_super")); 24060b57cec5SDimitry Andric QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 24070b57cec5SDimitry Andric assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 24080b57cec5SDimitry Andric ArgTys.push_back(argT); 24090b57cec5SDimitry Andric argT = Context->getObjCSelType(); 24100b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'SEL' type"); 24110b57cec5SDimitry Andric ArgTys.push_back(argT); 24120b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 24130b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 24140b57cec5SDimitry Andric MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24150b57cec5SDimitry Andric SourceLocation(), 24160b57cec5SDimitry Andric SourceLocation(), 24170b57cec5SDimitry Andric msgSendIdent, 24180b57cec5SDimitry Andric msgSendType, nullptr, 24190b57cec5SDimitry Andric SC_Extern); 24200b57cec5SDimitry Andric } 24210b57cec5SDimitry Andric 24220b57cec5SDimitry Andric // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); 24230b57cec5SDimitry Andric void RewriteObjC::SynthMsgSendFpretFunctionDecl() { 24240b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret"); 24250b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 24260b57cec5SDimitry Andric QualType argT = Context->getObjCIdType(); 24270b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'id' type"); 24280b57cec5SDimitry Andric ArgTys.push_back(argT); 24290b57cec5SDimitry Andric argT = Context->getObjCSelType(); 24300b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'SEL' type"); 24310b57cec5SDimitry Andric ArgTys.push_back(argT); 24320b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, 24330b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 24340b57cec5SDimitry Andric MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24350b57cec5SDimitry Andric SourceLocation(), 24360b57cec5SDimitry Andric SourceLocation(), 24370b57cec5SDimitry Andric msgSendIdent, msgSendType, 24380b57cec5SDimitry Andric nullptr, SC_Extern); 24390b57cec5SDimitry Andric } 24400b57cec5SDimitry Andric 24410b57cec5SDimitry Andric // SynthGetClassFunctionDecl - id objc_getClass(const char *name); 24420b57cec5SDimitry Andric void RewriteObjC::SynthGetClassFunctionDecl() { 24430b57cec5SDimitry Andric IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); 24440b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 24450b57cec5SDimitry Andric ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 24460b57cec5SDimitry Andric QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), 24470b57cec5SDimitry Andric ArgTys); 24480b57cec5SDimitry Andric GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24490b57cec5SDimitry Andric SourceLocation(), 24500b57cec5SDimitry Andric SourceLocation(), 24510b57cec5SDimitry Andric getClassIdent, getClassType, 24520b57cec5SDimitry Andric nullptr, SC_Extern); 24530b57cec5SDimitry Andric } 24540b57cec5SDimitry Andric 24550b57cec5SDimitry Andric // SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); 24560b57cec5SDimitry Andric void RewriteObjC::SynthGetSuperClassFunctionDecl() { 24570b57cec5SDimitry Andric IdentifierInfo *getSuperClassIdent = 24580b57cec5SDimitry Andric &Context->Idents.get("class_getSuperclass"); 24590b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 24600b57cec5SDimitry Andric ArgTys.push_back(Context->getObjCClassType()); 24610b57cec5SDimitry Andric QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 24620b57cec5SDimitry Andric ArgTys); 24630b57cec5SDimitry Andric GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24640b57cec5SDimitry Andric SourceLocation(), 24650b57cec5SDimitry Andric SourceLocation(), 24660b57cec5SDimitry Andric getSuperClassIdent, 24670b57cec5SDimitry Andric getClassType, nullptr, 24680b57cec5SDimitry Andric SC_Extern); 24690b57cec5SDimitry Andric } 24700b57cec5SDimitry Andric 24710b57cec5SDimitry Andric // SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name); 24720b57cec5SDimitry Andric void RewriteObjC::SynthGetMetaClassFunctionDecl() { 24730b57cec5SDimitry Andric IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); 24740b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 24750b57cec5SDimitry Andric ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 24760b57cec5SDimitry Andric QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), 24770b57cec5SDimitry Andric ArgTys); 24780b57cec5SDimitry Andric GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24790b57cec5SDimitry Andric SourceLocation(), 24800b57cec5SDimitry Andric SourceLocation(), 24810b57cec5SDimitry Andric getClassIdent, getClassType, 24820b57cec5SDimitry Andric nullptr, SC_Extern); 24830b57cec5SDimitry Andric } 24840b57cec5SDimitry Andric 24850b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { 24860b57cec5SDimitry Andric assert(Exp != nullptr && "Expected non-null ObjCStringLiteral"); 24870b57cec5SDimitry Andric QualType strType = getConstantStringStructType(); 24880b57cec5SDimitry Andric 24890b57cec5SDimitry Andric std::string S = "__NSConstantStringImpl_"; 24900b57cec5SDimitry Andric 24910b57cec5SDimitry Andric std::string tmpName = InFileName; 24920b57cec5SDimitry Andric unsigned i; 24930b57cec5SDimitry Andric for (i=0; i < tmpName.length(); i++) { 24940b57cec5SDimitry Andric char c = tmpName.at(i); 24950b57cec5SDimitry Andric // replace any non-alphanumeric characters with '_'. 24960b57cec5SDimitry Andric if (!isAlphanumeric(c)) 24970b57cec5SDimitry Andric tmpName[i] = '_'; 24980b57cec5SDimitry Andric } 24990b57cec5SDimitry Andric S += tmpName; 25000b57cec5SDimitry Andric S += "_"; 25010b57cec5SDimitry Andric S += utostr(NumObjCStringLiterals++); 25020b57cec5SDimitry Andric 25030b57cec5SDimitry Andric Preamble += "static __NSConstantStringImpl " + S; 25040b57cec5SDimitry Andric Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,"; 25050b57cec5SDimitry Andric Preamble += "0x000007c8,"; // utf8_str 25060b57cec5SDimitry Andric // The pretty printer for StringLiteral handles escape characters properly. 25070b57cec5SDimitry Andric std::string prettyBufS; 25080b57cec5SDimitry Andric llvm::raw_string_ostream prettyBuf(prettyBufS); 25090b57cec5SDimitry Andric Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts)); 25100b57cec5SDimitry Andric Preamble += prettyBuf.str(); 25110b57cec5SDimitry Andric Preamble += ","; 25120b57cec5SDimitry Andric Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; 25130b57cec5SDimitry Andric 25140b57cec5SDimitry Andric VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 25150b57cec5SDimitry Andric SourceLocation(), &Context->Idents.get(S), 25160b57cec5SDimitry Andric strType, nullptr, SC_Static); 25170b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 25180b57cec5SDimitry Andric DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation()); 25195ffd83dbSDimitry Andric Expr *Unop = UnaryOperator::Create( 25205ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), DRE, UO_AddrOf, 2521fe6060f1SDimitry Andric Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary, 25225ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 25230b57cec5SDimitry Andric // cast to NSConstantString * 25240b57cec5SDimitry Andric CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), 25250b57cec5SDimitry Andric CK_CPointerToObjCPointerCast, Unop); 25260b57cec5SDimitry Andric ReplaceStmt(Exp, cast); 25270b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 25280b57cec5SDimitry Andric return cast; 25290b57cec5SDimitry Andric } 25300b57cec5SDimitry Andric 25310b57cec5SDimitry Andric // struct objc_super { struct objc_object *receiver; struct objc_class *super; }; 25320b57cec5SDimitry Andric QualType RewriteObjC::getSuperStructType() { 25330b57cec5SDimitry Andric if (!SuperStructDecl) { 2534*5f757f3fSDimitry Andric SuperStructDecl = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 25350b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 25360b57cec5SDimitry Andric &Context->Idents.get("objc_super")); 25370b57cec5SDimitry Andric QualType FieldTypes[2]; 25380b57cec5SDimitry Andric 25390b57cec5SDimitry Andric // struct objc_object *receiver; 25400b57cec5SDimitry Andric FieldTypes[0] = Context->getObjCIdType(); 25410b57cec5SDimitry Andric // struct objc_class *super; 25420b57cec5SDimitry Andric FieldTypes[1] = Context->getObjCClassType(); 25430b57cec5SDimitry Andric 25440b57cec5SDimitry Andric // Create fields 25450b57cec5SDimitry Andric for (unsigned i = 0; i < 2; ++i) { 25460b57cec5SDimitry Andric SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, 25470b57cec5SDimitry Andric SourceLocation(), 25480b57cec5SDimitry Andric SourceLocation(), nullptr, 25490b57cec5SDimitry Andric FieldTypes[i], nullptr, 25500b57cec5SDimitry Andric /*BitWidth=*/nullptr, 25510b57cec5SDimitry Andric /*Mutable=*/false, 25520b57cec5SDimitry Andric ICIS_NoInit)); 25530b57cec5SDimitry Andric } 25540b57cec5SDimitry Andric 25550b57cec5SDimitry Andric SuperStructDecl->completeDefinition(); 25560b57cec5SDimitry Andric } 25570b57cec5SDimitry Andric return Context->getTagDeclType(SuperStructDecl); 25580b57cec5SDimitry Andric } 25590b57cec5SDimitry Andric 25600b57cec5SDimitry Andric QualType RewriteObjC::getConstantStringStructType() { 25610b57cec5SDimitry Andric if (!ConstantStringDecl) { 2562*5f757f3fSDimitry Andric ConstantStringDecl = RecordDecl::Create( 2563*5f757f3fSDimitry Andric *Context, TagTypeKind::Struct, TUDecl, SourceLocation(), 2564*5f757f3fSDimitry Andric SourceLocation(), &Context->Idents.get("__NSConstantStringImpl")); 25650b57cec5SDimitry Andric QualType FieldTypes[4]; 25660b57cec5SDimitry Andric 25670b57cec5SDimitry Andric // struct objc_object *receiver; 25680b57cec5SDimitry Andric FieldTypes[0] = Context->getObjCIdType(); 25690b57cec5SDimitry Andric // int flags; 25700b57cec5SDimitry Andric FieldTypes[1] = Context->IntTy; 25710b57cec5SDimitry Andric // char *str; 25720b57cec5SDimitry Andric FieldTypes[2] = Context->getPointerType(Context->CharTy); 25730b57cec5SDimitry Andric // long length; 25740b57cec5SDimitry Andric FieldTypes[3] = Context->LongTy; 25750b57cec5SDimitry Andric 25760b57cec5SDimitry Andric // Create fields 25770b57cec5SDimitry Andric for (unsigned i = 0; i < 4; ++i) { 25780b57cec5SDimitry Andric ConstantStringDecl->addDecl(FieldDecl::Create(*Context, 25790b57cec5SDimitry Andric ConstantStringDecl, 25800b57cec5SDimitry Andric SourceLocation(), 25810b57cec5SDimitry Andric SourceLocation(), nullptr, 25820b57cec5SDimitry Andric FieldTypes[i], nullptr, 25830b57cec5SDimitry Andric /*BitWidth=*/nullptr, 25840b57cec5SDimitry Andric /*Mutable=*/true, 25850b57cec5SDimitry Andric ICIS_NoInit)); 25860b57cec5SDimitry Andric } 25870b57cec5SDimitry Andric 25880b57cec5SDimitry Andric ConstantStringDecl->completeDefinition(); 25890b57cec5SDimitry Andric } 25900b57cec5SDimitry Andric return Context->getTagDeclType(ConstantStringDecl); 25910b57cec5SDimitry Andric } 25920b57cec5SDimitry Andric 25930b57cec5SDimitry Andric CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, 25940b57cec5SDimitry Andric QualType msgSendType, 25950b57cec5SDimitry Andric QualType returnType, 25960b57cec5SDimitry Andric SmallVectorImpl<QualType> &ArgTypes, 25970b57cec5SDimitry Andric SmallVectorImpl<Expr*> &MsgExprs, 25980b57cec5SDimitry Andric ObjCMethodDecl *Method) { 25990b57cec5SDimitry Andric // Create a reference to the objc_msgSend_stret() declaration. 26000b57cec5SDimitry Andric DeclRefExpr *STDRE = 26010b57cec5SDimitry Andric new (Context) DeclRefExpr(*Context, MsgSendStretFlavor, false, 26020b57cec5SDimitry Andric msgSendType, VK_LValue, SourceLocation()); 26030b57cec5SDimitry Andric // Need to cast objc_msgSend_stret to "void *" (see above comment). 26040b57cec5SDimitry Andric CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, 26050b57cec5SDimitry Andric Context->getPointerType(Context->VoidTy), 26060b57cec5SDimitry Andric CK_BitCast, STDRE); 26070b57cec5SDimitry Andric // Now do the "normal" pointer to function cast. 26080b57cec5SDimitry Andric QualType castType = getSimpleFunctionType(returnType, ArgTypes, 26090b57cec5SDimitry Andric Method ? Method->isVariadic() 26100b57cec5SDimitry Andric : false); 26110b57cec5SDimitry Andric castType = Context->getPointerType(castType); 26120b57cec5SDimitry Andric cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 26130b57cec5SDimitry Andric cast); 26140b57cec5SDimitry Andric 26150b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 26160b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); 26170b57cec5SDimitry Andric 2618a7dea167SDimitry Andric const auto *FT = msgSendType->castAs<FunctionType>(); 2619e8d8bef9SDimitry Andric CallExpr *STCE = 2620fe6060f1SDimitry Andric CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_PRValue, 2621e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 26220b57cec5SDimitry Andric return STCE; 26230b57cec5SDimitry Andric } 26240b57cec5SDimitry Andric 26250b57cec5SDimitry Andric Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 26260b57cec5SDimitry Andric SourceLocation StartLoc, 26270b57cec5SDimitry Andric SourceLocation EndLoc) { 26280b57cec5SDimitry Andric if (!SelGetUidFunctionDecl) 26290b57cec5SDimitry Andric SynthSelGetUidFunctionDecl(); 26300b57cec5SDimitry Andric if (!MsgSendFunctionDecl) 26310b57cec5SDimitry Andric SynthMsgSendFunctionDecl(); 26320b57cec5SDimitry Andric if (!MsgSendSuperFunctionDecl) 26330b57cec5SDimitry Andric SynthMsgSendSuperFunctionDecl(); 26340b57cec5SDimitry Andric if (!MsgSendStretFunctionDecl) 26350b57cec5SDimitry Andric SynthMsgSendStretFunctionDecl(); 26360b57cec5SDimitry Andric if (!MsgSendSuperStretFunctionDecl) 26370b57cec5SDimitry Andric SynthMsgSendSuperStretFunctionDecl(); 26380b57cec5SDimitry Andric if (!MsgSendFpretFunctionDecl) 26390b57cec5SDimitry Andric SynthMsgSendFpretFunctionDecl(); 26400b57cec5SDimitry Andric if (!GetClassFunctionDecl) 26410b57cec5SDimitry Andric SynthGetClassFunctionDecl(); 26420b57cec5SDimitry Andric if (!GetSuperClassFunctionDecl) 26430b57cec5SDimitry Andric SynthGetSuperClassFunctionDecl(); 26440b57cec5SDimitry Andric if (!GetMetaClassFunctionDecl) 26450b57cec5SDimitry Andric SynthGetMetaClassFunctionDecl(); 26460b57cec5SDimitry Andric 26470b57cec5SDimitry Andric // default to objc_msgSend(). 26480b57cec5SDimitry Andric FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 26490b57cec5SDimitry Andric // May need to use objc_msgSend_stret() as well. 26500b57cec5SDimitry Andric FunctionDecl *MsgSendStretFlavor = nullptr; 26510b57cec5SDimitry Andric if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { 26520b57cec5SDimitry Andric QualType resultType = mDecl->getReturnType(); 26530b57cec5SDimitry Andric if (resultType->isRecordType()) 26540b57cec5SDimitry Andric MsgSendStretFlavor = MsgSendStretFunctionDecl; 26550b57cec5SDimitry Andric else if (resultType->isRealFloatingType()) 26560b57cec5SDimitry Andric MsgSendFlavor = MsgSendFpretFunctionDecl; 26570b57cec5SDimitry Andric } 26580b57cec5SDimitry Andric 26590b57cec5SDimitry Andric // Synthesize a call to objc_msgSend(). 26600b57cec5SDimitry Andric SmallVector<Expr*, 8> MsgExprs; 26610b57cec5SDimitry Andric switch (Exp->getReceiverKind()) { 26620b57cec5SDimitry Andric case ObjCMessageExpr::SuperClass: { 26630b57cec5SDimitry Andric MsgSendFlavor = MsgSendSuperFunctionDecl; 26640b57cec5SDimitry Andric if (MsgSendStretFlavor) 26650b57cec5SDimitry Andric MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 26660b57cec5SDimitry Andric assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 26670b57cec5SDimitry Andric 26680b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 26690b57cec5SDimitry Andric 26700b57cec5SDimitry Andric SmallVector<Expr*, 4> InitExprs; 26710b57cec5SDimitry Andric 26720b57cec5SDimitry Andric // set the receiver to self, the first argument to all methods. 2673fe6060f1SDimitry Andric InitExprs.push_back(NoTypeInfoCStyleCastExpr( 2674fe6060f1SDimitry Andric Context, Context->getObjCIdType(), CK_BitCast, 2675fe6060f1SDimitry Andric new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false, 2676fe6060f1SDimitry Andric Context->getObjCIdType(), VK_PRValue, 2677fe6060f1SDimitry Andric SourceLocation()))); // set the 'receiver'. 26780b57cec5SDimitry Andric 26790b57cec5SDimitry Andric // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 26800b57cec5SDimitry Andric SmallVector<Expr*, 8> ClsExprs; 26810b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName())); 26820b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, 26830b57cec5SDimitry Andric ClsExprs, StartLoc, EndLoc); 26840b57cec5SDimitry Andric // (Class)objc_getClass("CurrentClass") 26850b57cec5SDimitry Andric CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 26860b57cec5SDimitry Andric Context->getObjCClassType(), 26870b57cec5SDimitry Andric CK_BitCast, Cls); 26880b57cec5SDimitry Andric ClsExprs.clear(); 26890b57cec5SDimitry Andric ClsExprs.push_back(ArgExpr); 26900b57cec5SDimitry Andric Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs, 26910b57cec5SDimitry Andric StartLoc, EndLoc); 26920b57cec5SDimitry Andric // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 26930b57cec5SDimitry Andric // To turn off a warning, type-cast to 'id' 26940b57cec5SDimitry Andric InitExprs.push_back( // set 'super class', using class_getSuperclass(). 26950b57cec5SDimitry Andric NoTypeInfoCStyleCastExpr(Context, 26960b57cec5SDimitry Andric Context->getObjCIdType(), 26970b57cec5SDimitry Andric CK_BitCast, Cls)); 26980b57cec5SDimitry Andric // struct objc_super 26990b57cec5SDimitry Andric QualType superType = getSuperStructType(); 27000b57cec5SDimitry Andric Expr *SuperRep; 27010b57cec5SDimitry Andric 27020b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 27030b57cec5SDimitry Andric SynthSuperConstructorFunctionDecl(); 27040b57cec5SDimitry Andric // Simulate a constructor call... 27050b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 27060b57cec5SDimitry Andric DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, 27070b57cec5SDimitry Andric VK_LValue, SourceLocation()); 2708e8d8bef9SDimitry Andric SuperRep = 2709e8d8bef9SDimitry Andric CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue, 2710e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 27110b57cec5SDimitry Andric // The code for super is a little tricky to prevent collision with 27120b57cec5SDimitry Andric // the structure definition in the header. The rewriter has it's own 27130b57cec5SDimitry Andric // internal definition (__rw_objc_super) that is uses. This is why 27140b57cec5SDimitry Andric // we need the cast below. For example: 27150b57cec5SDimitry Andric // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 27160b57cec5SDimitry Andric // 27175ffd83dbSDimitry Andric SuperRep = UnaryOperator::Create( 27185ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf, 2719fe6060f1SDimitry Andric Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary, 27205ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 27210b57cec5SDimitry Andric SuperRep = NoTypeInfoCStyleCastExpr(Context, 27220b57cec5SDimitry Andric Context->getPointerType(superType), 27230b57cec5SDimitry Andric CK_BitCast, SuperRep); 27240b57cec5SDimitry Andric } else { 27250b57cec5SDimitry Andric // (struct objc_super) { <exprs from above> } 27260b57cec5SDimitry Andric InitListExpr *ILE = 27270b57cec5SDimitry Andric new (Context) InitListExpr(*Context, SourceLocation(), InitExprs, 27280b57cec5SDimitry Andric SourceLocation()); 27290b57cec5SDimitry Andric TypeSourceInfo *superTInfo 27300b57cec5SDimitry Andric = Context->getTrivialTypeSourceInfo(superType); 27310b57cec5SDimitry Andric SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 27320b57cec5SDimitry Andric superType, VK_LValue, 27330b57cec5SDimitry Andric ILE, false); 27340b57cec5SDimitry Andric // struct objc_super * 27355ffd83dbSDimitry Andric SuperRep = UnaryOperator::Create( 27365ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf, 2737fe6060f1SDimitry Andric Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary, 27385ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 27390b57cec5SDimitry Andric } 27400b57cec5SDimitry Andric MsgExprs.push_back(SuperRep); 27410b57cec5SDimitry Andric break; 27420b57cec5SDimitry Andric } 27430b57cec5SDimitry Andric 27440b57cec5SDimitry Andric case ObjCMessageExpr::Class: { 27450b57cec5SDimitry Andric SmallVector<Expr*, 8> ClsExprs; 2746a7dea167SDimitry Andric auto *Class = 2747a7dea167SDimitry Andric Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface(); 27480b57cec5SDimitry Andric IdentifierInfo *clsName = Class->getIdentifier(); 27490b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(clsName->getName())); 27500b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs, 27510b57cec5SDimitry Andric StartLoc, EndLoc); 27520b57cec5SDimitry Andric MsgExprs.push_back(Cls); 27530b57cec5SDimitry Andric break; 27540b57cec5SDimitry Andric } 27550b57cec5SDimitry Andric 27560b57cec5SDimitry Andric case ObjCMessageExpr::SuperInstance:{ 27570b57cec5SDimitry Andric MsgSendFlavor = MsgSendSuperFunctionDecl; 27580b57cec5SDimitry Andric if (MsgSendStretFlavor) 27590b57cec5SDimitry Andric MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 27600b57cec5SDimitry Andric assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 27610b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 27620b57cec5SDimitry Andric SmallVector<Expr*, 4> InitExprs; 27630b57cec5SDimitry Andric 2764fe6060f1SDimitry Andric InitExprs.push_back(NoTypeInfoCStyleCastExpr( 2765fe6060f1SDimitry Andric Context, Context->getObjCIdType(), CK_BitCast, 2766fe6060f1SDimitry Andric new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false, 2767fe6060f1SDimitry Andric Context->getObjCIdType(), VK_PRValue, 2768fe6060f1SDimitry Andric SourceLocation()))); // set the 'receiver'. 27690b57cec5SDimitry Andric 27700b57cec5SDimitry Andric // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 27710b57cec5SDimitry Andric SmallVector<Expr*, 8> ClsExprs; 27720b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName())); 27730b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs, 27740b57cec5SDimitry Andric StartLoc, EndLoc); 27750b57cec5SDimitry Andric // (Class)objc_getClass("CurrentClass") 27760b57cec5SDimitry Andric CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 27770b57cec5SDimitry Andric Context->getObjCClassType(), 27780b57cec5SDimitry Andric CK_BitCast, Cls); 27790b57cec5SDimitry Andric ClsExprs.clear(); 27800b57cec5SDimitry Andric ClsExprs.push_back(ArgExpr); 27810b57cec5SDimitry Andric Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs, 27820b57cec5SDimitry Andric StartLoc, EndLoc); 27830b57cec5SDimitry Andric 27840b57cec5SDimitry Andric // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 27850b57cec5SDimitry Andric // To turn off a warning, type-cast to 'id' 27860b57cec5SDimitry Andric InitExprs.push_back( 27870b57cec5SDimitry Andric // set 'super class', using class_getSuperclass(). 27880b57cec5SDimitry Andric NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 27890b57cec5SDimitry Andric CK_BitCast, Cls)); 27900b57cec5SDimitry Andric // struct objc_super 27910b57cec5SDimitry Andric QualType superType = getSuperStructType(); 27920b57cec5SDimitry Andric Expr *SuperRep; 27930b57cec5SDimitry Andric 27940b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 27950b57cec5SDimitry Andric SynthSuperConstructorFunctionDecl(); 27960b57cec5SDimitry Andric // Simulate a constructor call... 27970b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 27980b57cec5SDimitry Andric DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, 27990b57cec5SDimitry Andric VK_LValue, SourceLocation()); 2800e8d8bef9SDimitry Andric SuperRep = 2801e8d8bef9SDimitry Andric CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue, 2802e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 28030b57cec5SDimitry Andric // The code for super is a little tricky to prevent collision with 28040b57cec5SDimitry Andric // the structure definition in the header. The rewriter has it's own 28050b57cec5SDimitry Andric // internal definition (__rw_objc_super) that is uses. This is why 28060b57cec5SDimitry Andric // we need the cast below. For example: 28070b57cec5SDimitry Andric // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 28080b57cec5SDimitry Andric // 28095ffd83dbSDimitry Andric SuperRep = UnaryOperator::Create( 28105ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf, 2811fe6060f1SDimitry Andric Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary, 28125ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 28130b57cec5SDimitry Andric SuperRep = NoTypeInfoCStyleCastExpr(Context, 28140b57cec5SDimitry Andric Context->getPointerType(superType), 28150b57cec5SDimitry Andric CK_BitCast, SuperRep); 28160b57cec5SDimitry Andric } else { 28170b57cec5SDimitry Andric // (struct objc_super) { <exprs from above> } 28180b57cec5SDimitry Andric InitListExpr *ILE = 28190b57cec5SDimitry Andric new (Context) InitListExpr(*Context, SourceLocation(), InitExprs, 28200b57cec5SDimitry Andric SourceLocation()); 28210b57cec5SDimitry Andric TypeSourceInfo *superTInfo 28220b57cec5SDimitry Andric = Context->getTrivialTypeSourceInfo(superType); 2823fe6060f1SDimitry Andric SuperRep = new (Context) CompoundLiteralExpr( 2824fe6060f1SDimitry Andric SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false); 28250b57cec5SDimitry Andric } 28260b57cec5SDimitry Andric MsgExprs.push_back(SuperRep); 28270b57cec5SDimitry Andric break; 28280b57cec5SDimitry Andric } 28290b57cec5SDimitry Andric 28300b57cec5SDimitry Andric case ObjCMessageExpr::Instance: { 28310b57cec5SDimitry Andric // Remove all type-casts because it may contain objc-style types; e.g. 28320b57cec5SDimitry Andric // Foo<Proto> *. 28330b57cec5SDimitry Andric Expr *recExpr = Exp->getInstanceReceiver(); 28340b57cec5SDimitry Andric while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) 28350b57cec5SDimitry Andric recExpr = CE->getSubExpr(); 28360b57cec5SDimitry Andric CastKind CK = recExpr->getType()->isObjCObjectPointerType() 28370b57cec5SDimitry Andric ? CK_BitCast : recExpr->getType()->isBlockPointerType() 28380b57cec5SDimitry Andric ? CK_BlockPointerToObjCPointerCast 28390b57cec5SDimitry Andric : CK_CPointerToObjCPointerCast; 28400b57cec5SDimitry Andric 28410b57cec5SDimitry Andric recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 28420b57cec5SDimitry Andric CK, recExpr); 28430b57cec5SDimitry Andric MsgExprs.push_back(recExpr); 28440b57cec5SDimitry Andric break; 28450b57cec5SDimitry Andric } 28460b57cec5SDimitry Andric } 28470b57cec5SDimitry Andric 28480b57cec5SDimitry Andric // Create a call to sel_registerName("selName"), it will be the 2nd argument. 28490b57cec5SDimitry Andric SmallVector<Expr*, 8> SelExprs; 28500b57cec5SDimitry Andric SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString())); 28510b57cec5SDimitry Andric CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 28520b57cec5SDimitry Andric SelExprs, StartLoc, EndLoc); 28530b57cec5SDimitry Andric MsgExprs.push_back(SelExp); 28540b57cec5SDimitry Andric 28550b57cec5SDimitry Andric // Now push any user supplied arguments. 28560b57cec5SDimitry Andric for (unsigned i = 0; i < Exp->getNumArgs(); i++) { 28570b57cec5SDimitry Andric Expr *userExpr = Exp->getArg(i); 28580b57cec5SDimitry Andric // Make all implicit casts explicit...ICE comes in handy:-) 28590b57cec5SDimitry Andric if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { 28600b57cec5SDimitry Andric // Reuse the ICE type, it is exactly what the doctor ordered. 28610b57cec5SDimitry Andric QualType type = ICE->getType(); 28620b57cec5SDimitry Andric if (needToScanForQualifiers(type)) 28630b57cec5SDimitry Andric type = Context->getObjCIdType(); 28640b57cec5SDimitry Andric // Make sure we convert "type (^)(...)" to "type (*)(...)". 28650b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(type); 28660b57cec5SDimitry Andric const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 28670b57cec5SDimitry Andric CastKind CK; 28680b57cec5SDimitry Andric if (SubExpr->getType()->isIntegralType(*Context) && 28690b57cec5SDimitry Andric type->isBooleanType()) { 28700b57cec5SDimitry Andric CK = CK_IntegralToBoolean; 28710b57cec5SDimitry Andric } else if (type->isObjCObjectPointerType()) { 28720b57cec5SDimitry Andric if (SubExpr->getType()->isBlockPointerType()) { 28730b57cec5SDimitry Andric CK = CK_BlockPointerToObjCPointerCast; 28740b57cec5SDimitry Andric } else if (SubExpr->getType()->isPointerType()) { 28750b57cec5SDimitry Andric CK = CK_CPointerToObjCPointerCast; 28760b57cec5SDimitry Andric } else { 28770b57cec5SDimitry Andric CK = CK_BitCast; 28780b57cec5SDimitry Andric } 28790b57cec5SDimitry Andric } else { 28800b57cec5SDimitry Andric CK = CK_BitCast; 28810b57cec5SDimitry Andric } 28820b57cec5SDimitry Andric 28830b57cec5SDimitry Andric userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); 28840b57cec5SDimitry Andric } 28850b57cec5SDimitry Andric // Make id<P...> cast into an 'id' cast. 28860b57cec5SDimitry Andric else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { 28870b57cec5SDimitry Andric if (CE->getType()->isObjCQualifiedIdType()) { 28880b57cec5SDimitry Andric while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) 28890b57cec5SDimitry Andric userExpr = CE->getSubExpr(); 28900b57cec5SDimitry Andric CastKind CK; 28910b57cec5SDimitry Andric if (userExpr->getType()->isIntegralType(*Context)) { 28920b57cec5SDimitry Andric CK = CK_IntegralToPointer; 28930b57cec5SDimitry Andric } else if (userExpr->getType()->isBlockPointerType()) { 28940b57cec5SDimitry Andric CK = CK_BlockPointerToObjCPointerCast; 28950b57cec5SDimitry Andric } else if (userExpr->getType()->isPointerType()) { 28960b57cec5SDimitry Andric CK = CK_CPointerToObjCPointerCast; 28970b57cec5SDimitry Andric } else { 28980b57cec5SDimitry Andric CK = CK_BitCast; 28990b57cec5SDimitry Andric } 29000b57cec5SDimitry Andric userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 29010b57cec5SDimitry Andric CK, userExpr); 29020b57cec5SDimitry Andric } 29030b57cec5SDimitry Andric } 29040b57cec5SDimitry Andric MsgExprs.push_back(userExpr); 29050b57cec5SDimitry Andric // We've transferred the ownership to MsgExprs. For now, we *don't* null 29060b57cec5SDimitry Andric // out the argument in the original expression (since we aren't deleting 29070b57cec5SDimitry Andric // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info. 29080b57cec5SDimitry Andric //Exp->setArg(i, 0); 29090b57cec5SDimitry Andric } 29100b57cec5SDimitry Andric // Generate the funky cast. 29110b57cec5SDimitry Andric CastExpr *cast; 29120b57cec5SDimitry Andric SmallVector<QualType, 8> ArgTypes; 29130b57cec5SDimitry Andric QualType returnType; 29140b57cec5SDimitry Andric 29150b57cec5SDimitry Andric // Push 'id' and 'SEL', the 2 implicit arguments. 29160b57cec5SDimitry Andric if (MsgSendFlavor == MsgSendSuperFunctionDecl) 29170b57cec5SDimitry Andric ArgTypes.push_back(Context->getPointerType(getSuperStructType())); 29180b57cec5SDimitry Andric else 29190b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCIdType()); 29200b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCSelType()); 29210b57cec5SDimitry Andric if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { 29220b57cec5SDimitry Andric // Push any user argument types. 29230b57cec5SDimitry Andric for (const auto *PI : OMD->parameters()) { 29240b57cec5SDimitry Andric QualType t = PI->getType()->isObjCQualifiedIdType() 29250b57cec5SDimitry Andric ? Context->getObjCIdType() 29260b57cec5SDimitry Andric : PI->getType(); 29270b57cec5SDimitry Andric // Make sure we convert "t (^)(...)" to "t (*)(...)". 29280b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(t); 29290b57cec5SDimitry Andric ArgTypes.push_back(t); 29300b57cec5SDimitry Andric } 29310b57cec5SDimitry Andric returnType = Exp->getType(); 29320b57cec5SDimitry Andric convertToUnqualifiedObjCType(returnType); 29330b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(returnType); 29340b57cec5SDimitry Andric } else { 29350b57cec5SDimitry Andric returnType = Context->getObjCIdType(); 29360b57cec5SDimitry Andric } 29370b57cec5SDimitry Andric // Get the type, we will need to reference it in a couple spots. 29380b57cec5SDimitry Andric QualType msgSendType = MsgSendFlavor->getType(); 29390b57cec5SDimitry Andric 29400b57cec5SDimitry Andric // Create a reference to the objc_msgSend() declaration. 29410b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr( 29420b57cec5SDimitry Andric *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation()); 29430b57cec5SDimitry Andric 29440b57cec5SDimitry Andric // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 29450b57cec5SDimitry Andric // If we don't do this cast, we get the following bizarre warning/note: 29460b57cec5SDimitry Andric // xx.m:13: warning: function called through a non-compatible type 29470b57cec5SDimitry Andric // xx.m:13: note: if this code is reached, the program will abort 29480b57cec5SDimitry Andric cast = NoTypeInfoCStyleCastExpr(Context, 29490b57cec5SDimitry Andric Context->getPointerType(Context->VoidTy), 29500b57cec5SDimitry Andric CK_BitCast, DRE); 29510b57cec5SDimitry Andric 29520b57cec5SDimitry Andric // Now do the "normal" pointer to function cast. 29530b57cec5SDimitry Andric // If we don't have a method decl, force a variadic cast. 29540b57cec5SDimitry Andric const ObjCMethodDecl *MD = Exp->getMethodDecl(); 29550b57cec5SDimitry Andric QualType castType = 29560b57cec5SDimitry Andric getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true); 29570b57cec5SDimitry Andric castType = Context->getPointerType(castType); 29580b57cec5SDimitry Andric cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 29590b57cec5SDimitry Andric cast); 29600b57cec5SDimitry Andric 29610b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 29620b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 29630b57cec5SDimitry Andric 2964a7dea167SDimitry Andric const auto *FT = msgSendType->castAs<FunctionType>(); 29650b57cec5SDimitry Andric CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), 2966fe6060f1SDimitry Andric VK_PRValue, EndLoc, FPOptionsOverride()); 29670b57cec5SDimitry Andric Stmt *ReplacingStmt = CE; 29680b57cec5SDimitry Andric if (MsgSendStretFlavor) { 29690b57cec5SDimitry Andric // We have the method which returns a struct/union. Must also generate 29700b57cec5SDimitry Andric // call to objc_msgSend_stret and hang both varieties on a conditional 29710b57cec5SDimitry Andric // expression which dictate which one to envoke depending on size of 29720b57cec5SDimitry Andric // method's return type. 29730b57cec5SDimitry Andric 29740b57cec5SDimitry Andric CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor, 29750b57cec5SDimitry Andric msgSendType, returnType, 29760b57cec5SDimitry Andric ArgTypes, MsgExprs, 29770b57cec5SDimitry Andric Exp->getMethodDecl()); 29780b57cec5SDimitry Andric 29790b57cec5SDimitry Andric // Build sizeof(returnType) 29800b57cec5SDimitry Andric UnaryExprOrTypeTraitExpr *sizeofExpr = 29810b57cec5SDimitry Andric new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf, 29820b57cec5SDimitry Andric Context->getTrivialTypeSourceInfo(returnType), 29830b57cec5SDimitry Andric Context->getSizeType(), SourceLocation(), 29840b57cec5SDimitry Andric SourceLocation()); 29850b57cec5SDimitry Andric // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 29860b57cec5SDimitry Andric // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. 29870b57cec5SDimitry Andric // For X86 it is more complicated and some kind of target specific routine 29880b57cec5SDimitry Andric // is needed to decide what to do. 29890b57cec5SDimitry Andric unsigned IntSize = 29900b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 29910b57cec5SDimitry Andric IntegerLiteral *limit = IntegerLiteral::Create(*Context, 29920b57cec5SDimitry Andric llvm::APInt(IntSize, 8), 29930b57cec5SDimitry Andric Context->IntTy, 29940b57cec5SDimitry Andric SourceLocation()); 29955ffd83dbSDimitry Andric BinaryOperator *lessThanExpr = BinaryOperator::Create( 2996fe6060f1SDimitry Andric *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue, 29975ffd83dbSDimitry Andric OK_Ordinary, SourceLocation(), FPOptionsOverride()); 29980b57cec5SDimitry Andric // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 2999fe6060f1SDimitry Andric ConditionalOperator *CondExpr = new (Context) ConditionalOperator( 3000fe6060f1SDimitry Andric lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType, 3001fe6060f1SDimitry Andric VK_PRValue, OK_Ordinary); 30020b57cec5SDimitry Andric ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 30030b57cec5SDimitry Andric CondExpr); 30040b57cec5SDimitry Andric } 30050b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 30060b57cec5SDimitry Andric return ReplacingStmt; 30070b57cec5SDimitry Andric } 30080b57cec5SDimitry Andric 30090b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { 30100b57cec5SDimitry Andric Stmt *ReplacingStmt = 30110b57cec5SDimitry Andric SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc()); 30120b57cec5SDimitry Andric 30130b57cec5SDimitry Andric // Now do the actual rewrite. 30140b57cec5SDimitry Andric ReplaceStmt(Exp, ReplacingStmt); 30150b57cec5SDimitry Andric 30160b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 30170b57cec5SDimitry Andric return ReplacingStmt; 30180b57cec5SDimitry Andric } 30190b57cec5SDimitry Andric 30200b57cec5SDimitry Andric // typedef struct objc_object Protocol; 30210b57cec5SDimitry Andric QualType RewriteObjC::getProtocolType() { 30220b57cec5SDimitry Andric if (!ProtocolTypeDecl) { 30230b57cec5SDimitry Andric TypeSourceInfo *TInfo 30240b57cec5SDimitry Andric = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); 30250b57cec5SDimitry Andric ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, 30260b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 30270b57cec5SDimitry Andric &Context->Idents.get("Protocol"), 30280b57cec5SDimitry Andric TInfo); 30290b57cec5SDimitry Andric } 30300b57cec5SDimitry Andric return Context->getTypeDeclType(ProtocolTypeDecl); 30310b57cec5SDimitry Andric } 30320b57cec5SDimitry Andric 30330b57cec5SDimitry Andric /// RewriteObjCProtocolExpr - Rewrite a protocol expression into 30340b57cec5SDimitry Andric /// a synthesized/forward data reference (to the protocol's metadata). 30350b57cec5SDimitry Andric /// The forward references (and metadata) are generated in 30360b57cec5SDimitry Andric /// RewriteObjC::HandleTranslationUnit(). 30370b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { 30380b57cec5SDimitry Andric std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); 30390b57cec5SDimitry Andric IdentifierInfo *ID = &Context->Idents.get(Name); 30400b57cec5SDimitry Andric VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 30410b57cec5SDimitry Andric SourceLocation(), ID, getProtocolType(), 30420b57cec5SDimitry Andric nullptr, SC_Extern); 30430b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr( 30440b57cec5SDimitry Andric *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation()); 30455ffd83dbSDimitry Andric Expr *DerefExpr = UnaryOperator::Create( 30465ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), DRE, UO_AddrOf, 3047fe6060f1SDimitry Andric Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary, 30485ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 30490b57cec5SDimitry Andric CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), 30500b57cec5SDimitry Andric CK_BitCast, 30510b57cec5SDimitry Andric DerefExpr); 30520b57cec5SDimitry Andric ReplaceStmt(Exp, castExpr); 30530b57cec5SDimitry Andric ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl()); 30540b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 30550b57cec5SDimitry Andric return castExpr; 30560b57cec5SDimitry Andric } 30570b57cec5SDimitry Andric 30580b57cec5SDimitry Andric bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, 30590b57cec5SDimitry Andric const char *endBuf) { 30600b57cec5SDimitry Andric while (startBuf < endBuf) { 30610b57cec5SDimitry Andric if (*startBuf == '#') { 30620b57cec5SDimitry Andric // Skip whitespace. 30630b57cec5SDimitry Andric for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf) 30640b57cec5SDimitry Andric ; 30650b57cec5SDimitry Andric if (!strncmp(startBuf, "if", strlen("if")) || 30660b57cec5SDimitry Andric !strncmp(startBuf, "ifdef", strlen("ifdef")) || 30670b57cec5SDimitry Andric !strncmp(startBuf, "ifndef", strlen("ifndef")) || 30680b57cec5SDimitry Andric !strncmp(startBuf, "define", strlen("define")) || 30690b57cec5SDimitry Andric !strncmp(startBuf, "undef", strlen("undef")) || 30700b57cec5SDimitry Andric !strncmp(startBuf, "else", strlen("else")) || 30710b57cec5SDimitry Andric !strncmp(startBuf, "elif", strlen("elif")) || 30720b57cec5SDimitry Andric !strncmp(startBuf, "endif", strlen("endif")) || 30730b57cec5SDimitry Andric !strncmp(startBuf, "pragma", strlen("pragma")) || 30740b57cec5SDimitry Andric !strncmp(startBuf, "include", strlen("include")) || 30750b57cec5SDimitry Andric !strncmp(startBuf, "import", strlen("import")) || 30760b57cec5SDimitry Andric !strncmp(startBuf, "include_next", strlen("include_next"))) 30770b57cec5SDimitry Andric return true; 30780b57cec5SDimitry Andric } 30790b57cec5SDimitry Andric startBuf++; 30800b57cec5SDimitry Andric } 30810b57cec5SDimitry Andric return false; 30820b57cec5SDimitry Andric } 30830b57cec5SDimitry Andric 30840b57cec5SDimitry Andric /// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to 30850b57cec5SDimitry Andric /// an objective-c class with ivars. 30860b57cec5SDimitry Andric void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 30870b57cec5SDimitry Andric std::string &Result) { 30880b57cec5SDimitry Andric assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); 30890b57cec5SDimitry Andric assert(CDecl->getName() != "" && 30900b57cec5SDimitry Andric "Name missing in SynthesizeObjCInternalStruct"); 30910b57cec5SDimitry Andric // Do not synthesize more than once. 30920b57cec5SDimitry Andric if (ObjCSynthesizedStructs.count(CDecl)) 30930b57cec5SDimitry Andric return; 30940b57cec5SDimitry Andric ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); 30950b57cec5SDimitry Andric int NumIvars = CDecl->ivar_size(); 30960b57cec5SDimitry Andric SourceLocation LocStart = CDecl->getBeginLoc(); 30970b57cec5SDimitry Andric SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc(); 30980b57cec5SDimitry Andric 30990b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 31000b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 31010b57cec5SDimitry Andric 31020b57cec5SDimitry Andric // If no ivars and no root or if its root, directly or indirectly, 31030b57cec5SDimitry Andric // have no ivars (thus not synthesized) then no need to synthesize this class. 31040b57cec5SDimitry Andric if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) && 31050b57cec5SDimitry Andric (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { 31060b57cec5SDimitry Andric endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 31070b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf, Result); 31080b57cec5SDimitry Andric return; 31090b57cec5SDimitry Andric } 31100b57cec5SDimitry Andric 31110b57cec5SDimitry Andric // FIXME: This has potential of causing problem. If 31120b57cec5SDimitry Andric // SynthesizeObjCInternalStruct is ever called recursively. 31130b57cec5SDimitry Andric Result += "\nstruct "; 31140b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 31150b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 31160b57cec5SDimitry Andric Result += "_IMPL"; 31170b57cec5SDimitry Andric 31180b57cec5SDimitry Andric if (NumIvars > 0) { 31190b57cec5SDimitry Andric const char *cursor = strchr(startBuf, '{'); 31200b57cec5SDimitry Andric assert((cursor && endBuf) 31210b57cec5SDimitry Andric && "SynthesizeObjCInternalStruct - malformed @interface"); 31220b57cec5SDimitry Andric // If the buffer contains preprocessor directives, we do more fine-grained 31230b57cec5SDimitry Andric // rewrites. This is intended to fix code that looks like (which occurs in 31240b57cec5SDimitry Andric // NSURL.h, for example): 31250b57cec5SDimitry Andric // 31260b57cec5SDimitry Andric // #ifdef XYZ 31270b57cec5SDimitry Andric // @interface Foo : NSObject 31280b57cec5SDimitry Andric // #else 31290b57cec5SDimitry Andric // @interface FooBar : NSObject 31300b57cec5SDimitry Andric // #endif 31310b57cec5SDimitry Andric // { 31320b57cec5SDimitry Andric // int i; 31330b57cec5SDimitry Andric // } 31340b57cec5SDimitry Andric // @end 31350b57cec5SDimitry Andric // 31360b57cec5SDimitry Andric // This clause is segregated to avoid breaking the common case. 31370b57cec5SDimitry Andric if (BufferContainsPPDirectives(startBuf, cursor)) { 31380b57cec5SDimitry Andric SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() : 31390b57cec5SDimitry Andric CDecl->getAtStartLoc(); 31400b57cec5SDimitry Andric const char *endHeader = SM->getCharacterData(L); 31410b57cec5SDimitry Andric endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts); 31420b57cec5SDimitry Andric 31430b57cec5SDimitry Andric if (CDecl->protocol_begin() != CDecl->protocol_end()) { 31440b57cec5SDimitry Andric // advance to the end of the referenced protocols. 31450b57cec5SDimitry Andric while (endHeader < cursor && *endHeader != '>') endHeader++; 31460b57cec5SDimitry Andric endHeader++; 31470b57cec5SDimitry Andric } 31480b57cec5SDimitry Andric // rewrite the original header 31490b57cec5SDimitry Andric ReplaceText(LocStart, endHeader-startBuf, Result); 31500b57cec5SDimitry Andric } else { 31510b57cec5SDimitry Andric // rewrite the original header *without* disturbing the '{' 31520b57cec5SDimitry Andric ReplaceText(LocStart, cursor-startBuf, Result); 31530b57cec5SDimitry Andric } 31540b57cec5SDimitry Andric if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 31550b57cec5SDimitry Andric Result = "\n struct "; 31560b57cec5SDimitry Andric Result += RCDecl->getNameAsString(); 31570b57cec5SDimitry Andric Result += "_IMPL "; 31580b57cec5SDimitry Andric Result += RCDecl->getNameAsString(); 31590b57cec5SDimitry Andric Result += "_IVARS;\n"; 31600b57cec5SDimitry Andric 31610b57cec5SDimitry Andric // insert the super class structure definition. 31620b57cec5SDimitry Andric SourceLocation OnePastCurly = 31630b57cec5SDimitry Andric LocStart.getLocWithOffset(cursor-startBuf+1); 31640b57cec5SDimitry Andric InsertText(OnePastCurly, Result); 31650b57cec5SDimitry Andric } 31660b57cec5SDimitry Andric cursor++; // past '{' 31670b57cec5SDimitry Andric 31680b57cec5SDimitry Andric // Now comment out any visibility specifiers. 31690b57cec5SDimitry Andric while (cursor < endBuf) { 31700b57cec5SDimitry Andric if (*cursor == '@') { 31710b57cec5SDimitry Andric SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 31720b57cec5SDimitry Andric // Skip whitespace. 31730b57cec5SDimitry Andric for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor) 31740b57cec5SDimitry Andric /*scan*/; 31750b57cec5SDimitry Andric 31760b57cec5SDimitry Andric // FIXME: presence of @public, etc. inside comment results in 31770b57cec5SDimitry Andric // this transformation as well, which is still correct c-code. 31780b57cec5SDimitry Andric if (!strncmp(cursor, "public", strlen("public")) || 31790b57cec5SDimitry Andric !strncmp(cursor, "private", strlen("private")) || 31800b57cec5SDimitry Andric !strncmp(cursor, "package", strlen("package")) || 31810b57cec5SDimitry Andric !strncmp(cursor, "protected", strlen("protected"))) 31820b57cec5SDimitry Andric InsertText(atLoc, "// "); 31830b57cec5SDimitry Andric } 31840b57cec5SDimitry Andric // FIXME: If there are cases where '<' is used in ivar declaration part 31850b57cec5SDimitry Andric // of user code, then scan the ivar list and use needToScanForQualifiers 31860b57cec5SDimitry Andric // for type checking. 31870b57cec5SDimitry Andric else if (*cursor == '<') { 31880b57cec5SDimitry Andric SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 31890b57cec5SDimitry Andric InsertText(atLoc, "/* "); 31900b57cec5SDimitry Andric cursor = strchr(cursor, '>'); 31910b57cec5SDimitry Andric cursor++; 31920b57cec5SDimitry Andric atLoc = LocStart.getLocWithOffset(cursor-startBuf); 31930b57cec5SDimitry Andric InsertText(atLoc, " */"); 31940b57cec5SDimitry Andric } else if (*cursor == '^') { // rewrite block specifier. 31950b57cec5SDimitry Andric SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf); 31960b57cec5SDimitry Andric ReplaceText(caretLoc, 1, "*"); 31970b57cec5SDimitry Andric } 31980b57cec5SDimitry Andric cursor++; 31990b57cec5SDimitry Andric } 32000b57cec5SDimitry Andric // Don't forget to add a ';'!! 32010b57cec5SDimitry Andric InsertText(LocEnd.getLocWithOffset(1), ";"); 32020b57cec5SDimitry Andric } else { // we don't have any instance variables - insert super struct. 32030b57cec5SDimitry Andric endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 32040b57cec5SDimitry Andric Result += " {\n struct "; 32050b57cec5SDimitry Andric Result += RCDecl->getNameAsString(); 32060b57cec5SDimitry Andric Result += "_IMPL "; 32070b57cec5SDimitry Andric Result += RCDecl->getNameAsString(); 32080b57cec5SDimitry Andric Result += "_IVARS;\n};\n"; 32090b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf, Result); 32100b57cec5SDimitry Andric } 32110b57cec5SDimitry Andric // Mark this struct as having been generated. 32120b57cec5SDimitry Andric if (!ObjCSynthesizedStructs.insert(CDecl).second) 32130b57cec5SDimitry Andric llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct"); 32140b57cec5SDimitry Andric } 32150b57cec5SDimitry Andric 32160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 32170b57cec5SDimitry Andric // Meta Data Emission 32180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 32190b57cec5SDimitry Andric 32200b57cec5SDimitry Andric /// RewriteImplementations - This routine rewrites all method implementations 32210b57cec5SDimitry Andric /// and emits meta-data. 32220b57cec5SDimitry Andric 32230b57cec5SDimitry Andric void RewriteObjC::RewriteImplementations() { 32240b57cec5SDimitry Andric int ClsDefCount = ClassImplementation.size(); 32250b57cec5SDimitry Andric int CatDefCount = CategoryImplementation.size(); 32260b57cec5SDimitry Andric 32270b57cec5SDimitry Andric // Rewrite implemented methods 32280b57cec5SDimitry Andric for (int i = 0; i < ClsDefCount; i++) 32290b57cec5SDimitry Andric RewriteImplementationDecl(ClassImplementation[i]); 32300b57cec5SDimitry Andric 32310b57cec5SDimitry Andric for (int i = 0; i < CatDefCount; i++) 32320b57cec5SDimitry Andric RewriteImplementationDecl(CategoryImplementation[i]); 32330b57cec5SDimitry Andric } 32340b57cec5SDimitry Andric 32350b57cec5SDimitry Andric void RewriteObjC::RewriteByRefString(std::string &ResultStr, 32360b57cec5SDimitry Andric const std::string &Name, 32370b57cec5SDimitry Andric ValueDecl *VD, bool def) { 32380b57cec5SDimitry Andric assert(BlockByRefDeclNo.count(VD) && 32390b57cec5SDimitry Andric "RewriteByRefString: ByRef decl missing"); 32400b57cec5SDimitry Andric if (def) 32410b57cec5SDimitry Andric ResultStr += "struct "; 32420b57cec5SDimitry Andric ResultStr += "__Block_byref_" + Name + 32430b57cec5SDimitry Andric "_" + utostr(BlockByRefDeclNo[VD]) ; 32440b57cec5SDimitry Andric } 32450b57cec5SDimitry Andric 32460b57cec5SDimitry Andric static bool HasLocalVariableExternalStorage(ValueDecl *VD) { 32470b57cec5SDimitry Andric if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 32480b57cec5SDimitry Andric return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage()); 32490b57cec5SDimitry Andric return false; 32500b57cec5SDimitry Andric } 32510b57cec5SDimitry Andric 32520b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, 32530b57cec5SDimitry Andric StringRef funcName, 32540b57cec5SDimitry Andric std::string Tag) { 32550b57cec5SDimitry Andric const FunctionType *AFT = CE->getFunctionType(); 32560b57cec5SDimitry Andric QualType RT = AFT->getReturnType(); 32570b57cec5SDimitry Andric std::string StructRef = "struct " + Tag; 32580b57cec5SDimitry Andric std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" + 32590b57cec5SDimitry Andric funcName.str() + "_" + "block_func_" + utostr(i); 32600b57cec5SDimitry Andric 32610b57cec5SDimitry Andric BlockDecl *BD = CE->getBlockDecl(); 32620b57cec5SDimitry Andric 32630b57cec5SDimitry Andric if (isa<FunctionNoProtoType>(AFT)) { 32640b57cec5SDimitry Andric // No user-supplied arguments. Still need to pass in a pointer to the 32650b57cec5SDimitry Andric // block (to reference imported block decl refs). 32660b57cec5SDimitry Andric S += "(" + StructRef + " *__cself)"; 32670b57cec5SDimitry Andric } else if (BD->param_empty()) { 32680b57cec5SDimitry Andric S += "(" + StructRef + " *__cself)"; 32690b57cec5SDimitry Andric } else { 32700b57cec5SDimitry Andric const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); 32710b57cec5SDimitry Andric assert(FT && "SynthesizeBlockFunc: No function proto"); 32720b57cec5SDimitry Andric S += '('; 32730b57cec5SDimitry Andric // first add the implicit argument. 32740b57cec5SDimitry Andric S += StructRef + " *__cself, "; 32750b57cec5SDimitry Andric std::string ParamStr; 32760b57cec5SDimitry Andric for (BlockDecl::param_iterator AI = BD->param_begin(), 32770b57cec5SDimitry Andric E = BD->param_end(); AI != E; ++AI) { 32780b57cec5SDimitry Andric if (AI != BD->param_begin()) S += ", "; 32790b57cec5SDimitry Andric ParamStr = (*AI)->getNameAsString(); 32800b57cec5SDimitry Andric QualType QT = (*AI)->getType(); 32810b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(QT); 32820b57cec5SDimitry Andric QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); 32830b57cec5SDimitry Andric S += ParamStr; 32840b57cec5SDimitry Andric } 32850b57cec5SDimitry Andric if (FT->isVariadic()) { 32860b57cec5SDimitry Andric if (!BD->param_empty()) S += ", "; 32870b57cec5SDimitry Andric S += "..."; 32880b57cec5SDimitry Andric } 32890b57cec5SDimitry Andric S += ')'; 32900b57cec5SDimitry Andric } 32910b57cec5SDimitry Andric S += " {\n"; 32920b57cec5SDimitry Andric 32930b57cec5SDimitry Andric // Create local declarations to avoid rewriting all closure decl ref exprs. 32940b57cec5SDimitry Andric // First, emit a declaration for all "by ref" decls. 32950b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 32960b57cec5SDimitry Andric E = BlockByRefDecls.end(); I != E; ++I) { 32970b57cec5SDimitry Andric S += " "; 32980b57cec5SDimitry Andric std::string Name = (*I)->getNameAsString(); 32990b57cec5SDimitry Andric std::string TypeString; 33000b57cec5SDimitry Andric RewriteByRefString(TypeString, Name, (*I)); 33010b57cec5SDimitry Andric TypeString += " *"; 33020b57cec5SDimitry Andric Name = TypeString + Name; 33030b57cec5SDimitry Andric S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; 33040b57cec5SDimitry Andric } 33050b57cec5SDimitry Andric // Next, emit a declaration for all "by copy" declarations. 33060b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 33070b57cec5SDimitry Andric E = BlockByCopyDecls.end(); I != E; ++I) { 33080b57cec5SDimitry Andric S += " "; 33090b57cec5SDimitry Andric // Handle nested closure invocation. For example: 33100b57cec5SDimitry Andric // 33110b57cec5SDimitry Andric // void (^myImportedClosure)(void); 33120b57cec5SDimitry Andric // myImportedClosure = ^(void) { setGlobalInt(x + y); }; 33130b57cec5SDimitry Andric // 33140b57cec5SDimitry Andric // void (^anotherClosure)(void); 33150b57cec5SDimitry Andric // anotherClosure = ^(void) { 33160b57cec5SDimitry Andric // myImportedClosure(); // import and invoke the closure 33170b57cec5SDimitry Andric // }; 33180b57cec5SDimitry Andric // 33190b57cec5SDimitry Andric if (isTopLevelBlockPointerType((*I)->getType())) { 33200b57cec5SDimitry Andric RewriteBlockPointerTypeVariable(S, (*I)); 33210b57cec5SDimitry Andric S += " = ("; 33220b57cec5SDimitry Andric RewriteBlockPointerType(S, (*I)->getType()); 33230b57cec5SDimitry Andric S += ")"; 33240b57cec5SDimitry Andric S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n"; 33250b57cec5SDimitry Andric } 33260b57cec5SDimitry Andric else { 33270b57cec5SDimitry Andric std::string Name = (*I)->getNameAsString(); 33280b57cec5SDimitry Andric QualType QT = (*I)->getType(); 33290b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(*I)) 33300b57cec5SDimitry Andric QT = Context->getPointerType(QT); 33310b57cec5SDimitry Andric QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 33320b57cec5SDimitry Andric S += Name + " = __cself->" + 33330b57cec5SDimitry Andric (*I)->getNameAsString() + "; // bound by copy\n"; 33340b57cec5SDimitry Andric } 33350b57cec5SDimitry Andric } 33360b57cec5SDimitry Andric std::string RewrittenStr = RewrittenBlockExprs[CE]; 33370b57cec5SDimitry Andric const char *cstr = RewrittenStr.c_str(); 33380b57cec5SDimitry Andric while (*cstr++ != '{') ; 33390b57cec5SDimitry Andric S += cstr; 33400b57cec5SDimitry Andric S += "\n"; 33410b57cec5SDimitry Andric return S; 33420b57cec5SDimitry Andric } 33430b57cec5SDimitry Andric 33440b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 33450b57cec5SDimitry Andric StringRef funcName, 33460b57cec5SDimitry Andric std::string Tag) { 33470b57cec5SDimitry Andric std::string StructRef = "struct " + Tag; 33480b57cec5SDimitry Andric std::string S = "static void __"; 33490b57cec5SDimitry Andric 33500b57cec5SDimitry Andric S += funcName; 33510b57cec5SDimitry Andric S += "_block_copy_" + utostr(i); 33520b57cec5SDimitry Andric S += "(" + StructRef; 33530b57cec5SDimitry Andric S += "*dst, " + StructRef; 33540b57cec5SDimitry Andric S += "*src) {"; 33550b57cec5SDimitry Andric for (ValueDecl *VD : ImportedBlockDecls) { 33560b57cec5SDimitry Andric S += "_Block_object_assign((void*)&dst->"; 33570b57cec5SDimitry Andric S += VD->getNameAsString(); 33580b57cec5SDimitry Andric S += ", (void*)src->"; 33590b57cec5SDimitry Andric S += VD->getNameAsString(); 33600b57cec5SDimitry Andric if (BlockByRefDeclsPtrSet.count(VD)) 33610b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 33620b57cec5SDimitry Andric else if (VD->getType()->isBlockPointerType()) 33630b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 33640b57cec5SDimitry Andric else 33650b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 33660b57cec5SDimitry Andric } 33670b57cec5SDimitry Andric S += "}\n"; 33680b57cec5SDimitry Andric 33690b57cec5SDimitry Andric S += "\nstatic void __"; 33700b57cec5SDimitry Andric S += funcName; 33710b57cec5SDimitry Andric S += "_block_dispose_" + utostr(i); 33720b57cec5SDimitry Andric S += "(" + StructRef; 33730b57cec5SDimitry Andric S += "*src) {"; 33740b57cec5SDimitry Andric for (ValueDecl *VD : ImportedBlockDecls) { 33750b57cec5SDimitry Andric S += "_Block_object_dispose((void*)src->"; 33760b57cec5SDimitry Andric S += VD->getNameAsString(); 33770b57cec5SDimitry Andric if (BlockByRefDeclsPtrSet.count(VD)) 33780b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 33790b57cec5SDimitry Andric else if (VD->getType()->isBlockPointerType()) 33800b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 33810b57cec5SDimitry Andric else 33820b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 33830b57cec5SDimitry Andric } 33840b57cec5SDimitry Andric S += "}\n"; 33850b57cec5SDimitry Andric return S; 33860b57cec5SDimitry Andric } 33870b57cec5SDimitry Andric 33880b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 33890b57cec5SDimitry Andric std::string Desc) { 33900b57cec5SDimitry Andric std::string S = "\nstruct " + Tag; 33910b57cec5SDimitry Andric std::string Constructor = " " + Tag; 33920b57cec5SDimitry Andric 33930b57cec5SDimitry Andric S += " {\n struct __block_impl impl;\n"; 33940b57cec5SDimitry Andric S += " struct " + Desc; 33950b57cec5SDimitry Andric S += "* Desc;\n"; 33960b57cec5SDimitry Andric 33970b57cec5SDimitry Andric Constructor += "(void *fp, "; // Invoke function pointer. 33980b57cec5SDimitry Andric Constructor += "struct " + Desc; // Descriptor pointer. 33990b57cec5SDimitry Andric Constructor += " *desc"; 34000b57cec5SDimitry Andric 34010b57cec5SDimitry Andric if (BlockDeclRefs.size()) { 34020b57cec5SDimitry Andric // Output all "by copy" declarations. 34030b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 34040b57cec5SDimitry Andric E = BlockByCopyDecls.end(); I != E; ++I) { 34050b57cec5SDimitry Andric S += " "; 34060b57cec5SDimitry Andric std::string FieldName = (*I)->getNameAsString(); 34070b57cec5SDimitry Andric std::string ArgName = "_" + FieldName; 34080b57cec5SDimitry Andric // Handle nested closure invocation. For example: 34090b57cec5SDimitry Andric // 34100b57cec5SDimitry Andric // void (^myImportedBlock)(void); 34110b57cec5SDimitry Andric // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 34120b57cec5SDimitry Andric // 34130b57cec5SDimitry Andric // void (^anotherBlock)(void); 34140b57cec5SDimitry Andric // anotherBlock = ^(void) { 34150b57cec5SDimitry Andric // myImportedBlock(); // import and invoke the closure 34160b57cec5SDimitry Andric // }; 34170b57cec5SDimitry Andric // 34180b57cec5SDimitry Andric if (isTopLevelBlockPointerType((*I)->getType())) { 34190b57cec5SDimitry Andric S += "struct __block_impl *"; 34200b57cec5SDimitry Andric Constructor += ", void *" + ArgName; 34210b57cec5SDimitry Andric } else { 34220b57cec5SDimitry Andric QualType QT = (*I)->getType(); 34230b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(*I)) 34240b57cec5SDimitry Andric QT = Context->getPointerType(QT); 34250b57cec5SDimitry Andric QT.getAsStringInternal(FieldName, Context->getPrintingPolicy()); 34260b57cec5SDimitry Andric QT.getAsStringInternal(ArgName, Context->getPrintingPolicy()); 34270b57cec5SDimitry Andric Constructor += ", " + ArgName; 34280b57cec5SDimitry Andric } 34290b57cec5SDimitry Andric S += FieldName + ";\n"; 34300b57cec5SDimitry Andric } 34310b57cec5SDimitry Andric // Output all "by ref" declarations. 34320b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 34330b57cec5SDimitry Andric E = BlockByRefDecls.end(); I != E; ++I) { 34340b57cec5SDimitry Andric S += " "; 34350b57cec5SDimitry Andric std::string FieldName = (*I)->getNameAsString(); 34360b57cec5SDimitry Andric std::string ArgName = "_" + FieldName; 34370b57cec5SDimitry Andric { 34380b57cec5SDimitry Andric std::string TypeString; 34390b57cec5SDimitry Andric RewriteByRefString(TypeString, FieldName, (*I)); 34400b57cec5SDimitry Andric TypeString += " *"; 34410b57cec5SDimitry Andric FieldName = TypeString + FieldName; 34420b57cec5SDimitry Andric ArgName = TypeString + ArgName; 34430b57cec5SDimitry Andric Constructor += ", " + ArgName; 34440b57cec5SDimitry Andric } 34450b57cec5SDimitry Andric S += FieldName + "; // by ref\n"; 34460b57cec5SDimitry Andric } 34470b57cec5SDimitry Andric // Finish writing the constructor. 34480b57cec5SDimitry Andric Constructor += ", int flags=0)"; 34490b57cec5SDimitry Andric // Initialize all "by copy" arguments. 34500b57cec5SDimitry Andric bool firsTime = true; 34510b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 34520b57cec5SDimitry Andric E = BlockByCopyDecls.end(); I != E; ++I) { 34530b57cec5SDimitry Andric std::string Name = (*I)->getNameAsString(); 34540b57cec5SDimitry Andric if (firsTime) { 34550b57cec5SDimitry Andric Constructor += " : "; 34560b57cec5SDimitry Andric firsTime = false; 34570b57cec5SDimitry Andric } 34580b57cec5SDimitry Andric else 34590b57cec5SDimitry Andric Constructor += ", "; 34600b57cec5SDimitry Andric if (isTopLevelBlockPointerType((*I)->getType())) 34610b57cec5SDimitry Andric Constructor += Name + "((struct __block_impl *)_" + Name + ")"; 34620b57cec5SDimitry Andric else 34630b57cec5SDimitry Andric Constructor += Name + "(_" + Name + ")"; 34640b57cec5SDimitry Andric } 34650b57cec5SDimitry Andric // Initialize all "by ref" arguments. 34660b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 34670b57cec5SDimitry Andric E = BlockByRefDecls.end(); I != E; ++I) { 34680b57cec5SDimitry Andric std::string Name = (*I)->getNameAsString(); 34690b57cec5SDimitry Andric if (firsTime) { 34700b57cec5SDimitry Andric Constructor += " : "; 34710b57cec5SDimitry Andric firsTime = false; 34720b57cec5SDimitry Andric } 34730b57cec5SDimitry Andric else 34740b57cec5SDimitry Andric Constructor += ", "; 34750b57cec5SDimitry Andric Constructor += Name + "(_" + Name + "->__forwarding)"; 34760b57cec5SDimitry Andric } 34770b57cec5SDimitry Andric 34780b57cec5SDimitry Andric Constructor += " {\n"; 34790b57cec5SDimitry Andric if (GlobalVarDecl) 34800b57cec5SDimitry Andric Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 34810b57cec5SDimitry Andric else 34820b57cec5SDimitry Andric Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 34830b57cec5SDimitry Andric Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 34840b57cec5SDimitry Andric 34850b57cec5SDimitry Andric Constructor += " Desc = desc;\n"; 34860b57cec5SDimitry Andric } else { 34870b57cec5SDimitry Andric // Finish writing the constructor. 34880b57cec5SDimitry Andric Constructor += ", int flags=0) {\n"; 34890b57cec5SDimitry Andric if (GlobalVarDecl) 34900b57cec5SDimitry Andric Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 34910b57cec5SDimitry Andric else 34920b57cec5SDimitry Andric Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 34930b57cec5SDimitry Andric Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 34940b57cec5SDimitry Andric Constructor += " Desc = desc;\n"; 34950b57cec5SDimitry Andric } 34960b57cec5SDimitry Andric Constructor += " "; 34970b57cec5SDimitry Andric Constructor += "}\n"; 34980b57cec5SDimitry Andric S += Constructor; 34990b57cec5SDimitry Andric S += "};\n"; 35000b57cec5SDimitry Andric return S; 35010b57cec5SDimitry Andric } 35020b57cec5SDimitry Andric 35030b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, 35040b57cec5SDimitry Andric std::string ImplTag, int i, 35050b57cec5SDimitry Andric StringRef FunName, 35060b57cec5SDimitry Andric unsigned hasCopy) { 35070b57cec5SDimitry Andric std::string S = "\nstatic struct " + DescTag; 35080b57cec5SDimitry Andric 35090b57cec5SDimitry Andric S += " {\n unsigned long reserved;\n"; 35100b57cec5SDimitry Andric S += " unsigned long Block_size;\n"; 35110b57cec5SDimitry Andric if (hasCopy) { 35120b57cec5SDimitry Andric S += " void (*copy)(struct "; 35130b57cec5SDimitry Andric S += ImplTag; S += "*, struct "; 35140b57cec5SDimitry Andric S += ImplTag; S += "*);\n"; 35150b57cec5SDimitry Andric 35160b57cec5SDimitry Andric S += " void (*dispose)(struct "; 35170b57cec5SDimitry Andric S += ImplTag; S += "*);\n"; 35180b57cec5SDimitry Andric } 35190b57cec5SDimitry Andric S += "} "; 35200b57cec5SDimitry Andric 35210b57cec5SDimitry Andric S += DescTag + "_DATA = { 0, sizeof(struct "; 35220b57cec5SDimitry Andric S += ImplTag + ")"; 35230b57cec5SDimitry Andric if (hasCopy) { 35240b57cec5SDimitry Andric S += ", __" + FunName.str() + "_block_copy_" + utostr(i); 35250b57cec5SDimitry Andric S += ", __" + FunName.str() + "_block_dispose_" + utostr(i); 35260b57cec5SDimitry Andric } 35270b57cec5SDimitry Andric S += "};\n"; 35280b57cec5SDimitry Andric return S; 35290b57cec5SDimitry Andric } 35300b57cec5SDimitry Andric 35310b57cec5SDimitry Andric void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, 35320b57cec5SDimitry Andric StringRef FunName) { 35330b57cec5SDimitry Andric // Insert declaration for the function in which block literal is used. 35340b57cec5SDimitry Andric if (CurFunctionDeclToDeclareForBlock && !Blocks.empty()) 35350b57cec5SDimitry Andric RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 35360b57cec5SDimitry Andric bool RewriteSC = (GlobalVarDecl && 35370b57cec5SDimitry Andric !Blocks.empty() && 35380b57cec5SDimitry Andric GlobalVarDecl->getStorageClass() == SC_Static && 35390b57cec5SDimitry Andric GlobalVarDecl->getType().getCVRQualifiers()); 35400b57cec5SDimitry Andric if (RewriteSC) { 35410b57cec5SDimitry Andric std::string SC(" void __"); 35420b57cec5SDimitry Andric SC += GlobalVarDecl->getNameAsString(); 35430b57cec5SDimitry Andric SC += "() {}"; 35440b57cec5SDimitry Andric InsertText(FunLocStart, SC); 35450b57cec5SDimitry Andric } 35460b57cec5SDimitry Andric 35470b57cec5SDimitry Andric // Insert closures that were part of the function. 35480b57cec5SDimitry Andric for (unsigned i = 0, count=0; i < Blocks.size(); i++) { 35490b57cec5SDimitry Andric CollectBlockDeclRefInfo(Blocks[i]); 35500b57cec5SDimitry Andric // Need to copy-in the inner copied-in variables not actually used in this 35510b57cec5SDimitry Andric // block. 35520b57cec5SDimitry Andric for (int j = 0; j < InnerDeclRefsCount[i]; j++) { 35530b57cec5SDimitry Andric DeclRefExpr *Exp = InnerDeclRefs[count++]; 35540b57cec5SDimitry Andric ValueDecl *VD = Exp->getDecl(); 35550b57cec5SDimitry Andric BlockDeclRefs.push_back(Exp); 35560b57cec5SDimitry Andric if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { 35570b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.insert(VD); 35580b57cec5SDimitry Andric BlockByCopyDecls.push_back(VD); 35590b57cec5SDimitry Andric } 35600b57cec5SDimitry Andric if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { 35610b57cec5SDimitry Andric BlockByRefDeclsPtrSet.insert(VD); 35620b57cec5SDimitry Andric BlockByRefDecls.push_back(VD); 35630b57cec5SDimitry Andric } 35640b57cec5SDimitry Andric // imported objects in the inner blocks not used in the outer 35650b57cec5SDimitry Andric // blocks must be copied/disposed in the outer block as well. 35660b57cec5SDimitry Andric if (VD->hasAttr<BlocksAttr>() || 35670b57cec5SDimitry Andric VD->getType()->isObjCObjectPointerType() || 35680b57cec5SDimitry Andric VD->getType()->isBlockPointerType()) 35690b57cec5SDimitry Andric ImportedBlockDecls.insert(VD); 35700b57cec5SDimitry Andric } 35710b57cec5SDimitry Andric 35720b57cec5SDimitry Andric std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i); 35730b57cec5SDimitry Andric std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i); 35740b57cec5SDimitry Andric 35750b57cec5SDimitry Andric std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); 35760b57cec5SDimitry Andric 35770b57cec5SDimitry Andric InsertText(FunLocStart, CI); 35780b57cec5SDimitry Andric 35790b57cec5SDimitry Andric std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); 35800b57cec5SDimitry Andric 35810b57cec5SDimitry Andric InsertText(FunLocStart, CF); 35820b57cec5SDimitry Andric 35830b57cec5SDimitry Andric if (ImportedBlockDecls.size()) { 35840b57cec5SDimitry Andric std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); 35850b57cec5SDimitry Andric InsertText(FunLocStart, HF); 35860b57cec5SDimitry Andric } 35870b57cec5SDimitry Andric std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, 35880b57cec5SDimitry Andric ImportedBlockDecls.size() > 0); 35890b57cec5SDimitry Andric InsertText(FunLocStart, BD); 35900b57cec5SDimitry Andric 35910b57cec5SDimitry Andric BlockDeclRefs.clear(); 35920b57cec5SDimitry Andric BlockByRefDecls.clear(); 35930b57cec5SDimitry Andric BlockByRefDeclsPtrSet.clear(); 35940b57cec5SDimitry Andric BlockByCopyDecls.clear(); 35950b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.clear(); 35960b57cec5SDimitry Andric ImportedBlockDecls.clear(); 35970b57cec5SDimitry Andric } 35980b57cec5SDimitry Andric if (RewriteSC) { 35990b57cec5SDimitry Andric // Must insert any 'const/volatile/static here. Since it has been 36000b57cec5SDimitry Andric // removed as result of rewriting of block literals. 36010b57cec5SDimitry Andric std::string SC; 36020b57cec5SDimitry Andric if (GlobalVarDecl->getStorageClass() == SC_Static) 36030b57cec5SDimitry Andric SC = "static "; 36040b57cec5SDimitry Andric if (GlobalVarDecl->getType().isConstQualified()) 36050b57cec5SDimitry Andric SC += "const "; 36060b57cec5SDimitry Andric if (GlobalVarDecl->getType().isVolatileQualified()) 36070b57cec5SDimitry Andric SC += "volatile "; 36080b57cec5SDimitry Andric if (GlobalVarDecl->getType().isRestrictQualified()) 36090b57cec5SDimitry Andric SC += "restrict "; 36100b57cec5SDimitry Andric InsertText(FunLocStart, SC); 36110b57cec5SDimitry Andric } 36120b57cec5SDimitry Andric 36130b57cec5SDimitry Andric Blocks.clear(); 36140b57cec5SDimitry Andric InnerDeclRefsCount.clear(); 36150b57cec5SDimitry Andric InnerDeclRefs.clear(); 36160b57cec5SDimitry Andric RewrittenBlockExprs.clear(); 36170b57cec5SDimitry Andric } 36180b57cec5SDimitry Andric 36190b57cec5SDimitry Andric void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { 36200b57cec5SDimitry Andric SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 36210b57cec5SDimitry Andric StringRef FuncName = FD->getName(); 36220b57cec5SDimitry Andric 36230b57cec5SDimitry Andric SynthesizeBlockLiterals(FunLocStart, FuncName); 36240b57cec5SDimitry Andric } 36250b57cec5SDimitry Andric 36260b57cec5SDimitry Andric static void BuildUniqueMethodName(std::string &Name, 36270b57cec5SDimitry Andric ObjCMethodDecl *MD) { 36280b57cec5SDimitry Andric ObjCInterfaceDecl *IFace = MD->getClassInterface(); 36295ffd83dbSDimitry Andric Name = std::string(IFace->getName()); 36300b57cec5SDimitry Andric Name += "__" + MD->getSelector().getAsString(); 36310b57cec5SDimitry Andric // Convert colons to underscores. 36320b57cec5SDimitry Andric std::string::size_type loc = 0; 36330b57cec5SDimitry Andric while ((loc = Name.find(':', loc)) != std::string::npos) 36340b57cec5SDimitry Andric Name.replace(loc, 1, "_"); 36350b57cec5SDimitry Andric } 36360b57cec5SDimitry Andric 36370b57cec5SDimitry Andric void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { 36380b57cec5SDimitry Andric // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); 36390b57cec5SDimitry Andric // SourceLocation FunLocStart = MD->getBeginLoc(); 36400b57cec5SDimitry Andric SourceLocation FunLocStart = MD->getBeginLoc(); 36410b57cec5SDimitry Andric std::string FuncName; 36420b57cec5SDimitry Andric BuildUniqueMethodName(FuncName, MD); 36430b57cec5SDimitry Andric SynthesizeBlockLiterals(FunLocStart, FuncName); 36440b57cec5SDimitry Andric } 36450b57cec5SDimitry Andric 36460b57cec5SDimitry Andric void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) { 36470b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 36480b57cec5SDimitry Andric if (SubStmt) { 36490b57cec5SDimitry Andric if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) 36500b57cec5SDimitry Andric GetBlockDeclRefExprs(CBE->getBody()); 36510b57cec5SDimitry Andric else 36520b57cec5SDimitry Andric GetBlockDeclRefExprs(SubStmt); 36530b57cec5SDimitry Andric } 36540b57cec5SDimitry Andric // Handle specific things. 36550b57cec5SDimitry Andric if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) 36560b57cec5SDimitry Andric if (DRE->refersToEnclosingVariableOrCapture() || 36570b57cec5SDimitry Andric HasLocalVariableExternalStorage(DRE->getDecl())) 36580b57cec5SDimitry Andric // FIXME: Handle enums. 36590b57cec5SDimitry Andric BlockDeclRefs.push_back(DRE); 36600b57cec5SDimitry Andric } 36610b57cec5SDimitry Andric 36620b57cec5SDimitry Andric void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, 36630b57cec5SDimitry Andric SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs, 36640b57cec5SDimitry Andric llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) { 36650b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 36660b57cec5SDimitry Andric if (SubStmt) { 36670b57cec5SDimitry Andric if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) { 36680b57cec5SDimitry Andric InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl())); 36690b57cec5SDimitry Andric GetInnerBlockDeclRefExprs(CBE->getBody(), 36700b57cec5SDimitry Andric InnerBlockDeclRefs, 36710b57cec5SDimitry Andric InnerContexts); 36720b57cec5SDimitry Andric } 36730b57cec5SDimitry Andric else 36740b57cec5SDimitry Andric GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts); 36750b57cec5SDimitry Andric } 36760b57cec5SDimitry Andric // Handle specific things. 36770b57cec5SDimitry Andric if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 36780b57cec5SDimitry Andric if (DRE->refersToEnclosingVariableOrCapture() || 36790b57cec5SDimitry Andric HasLocalVariableExternalStorage(DRE->getDecl())) { 36800b57cec5SDimitry Andric if (!InnerContexts.count(DRE->getDecl()->getDeclContext())) 36810b57cec5SDimitry Andric InnerBlockDeclRefs.push_back(DRE); 36820b57cec5SDimitry Andric if (VarDecl *Var = cast<VarDecl>(DRE->getDecl())) 36830b57cec5SDimitry Andric if (Var->isFunctionOrMethodVarDecl()) 36840b57cec5SDimitry Andric ImportedLocalExternalDecls.insert(Var); 36850b57cec5SDimitry Andric } 36860b57cec5SDimitry Andric } 36870b57cec5SDimitry Andric } 36880b57cec5SDimitry Andric 36890b57cec5SDimitry Andric /// convertFunctionTypeOfBlocks - This routine converts a function type 36900b57cec5SDimitry Andric /// whose result type may be a block pointer or whose argument type(s) 36910b57cec5SDimitry Andric /// might be block pointers to an equivalent function type replacing 36920b57cec5SDimitry Andric /// all block pointers to function pointers. 36930b57cec5SDimitry Andric QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { 36940b57cec5SDimitry Andric const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 36950b57cec5SDimitry Andric // FTP will be null for closures that don't take arguments. 36960b57cec5SDimitry Andric // Generate a funky cast. 36970b57cec5SDimitry Andric SmallVector<QualType, 8> ArgTypes; 36980b57cec5SDimitry Andric QualType Res = FT->getReturnType(); 36990b57cec5SDimitry Andric bool HasBlockType = convertBlockPointerToFunctionPointer(Res); 37000b57cec5SDimitry Andric 37010b57cec5SDimitry Andric if (FTP) { 37020b57cec5SDimitry Andric for (auto &I : FTP->param_types()) { 37030b57cec5SDimitry Andric QualType t = I; 37040b57cec5SDimitry Andric // Make sure we convert "t (^)(...)" to "t (*)(...)". 37050b57cec5SDimitry Andric if (convertBlockPointerToFunctionPointer(t)) 37060b57cec5SDimitry Andric HasBlockType = true; 37070b57cec5SDimitry Andric ArgTypes.push_back(t); 37080b57cec5SDimitry Andric } 37090b57cec5SDimitry Andric } 37100b57cec5SDimitry Andric QualType FuncType; 37110b57cec5SDimitry Andric // FIXME. Does this work if block takes no argument but has a return type 37120b57cec5SDimitry Andric // which is of block type? 37130b57cec5SDimitry Andric if (HasBlockType) 37140b57cec5SDimitry Andric FuncType = getSimpleFunctionType(Res, ArgTypes); 37150b57cec5SDimitry Andric else FuncType = QualType(FT, 0); 37160b57cec5SDimitry Andric return FuncType; 37170b57cec5SDimitry Andric } 37180b57cec5SDimitry Andric 37190b57cec5SDimitry Andric Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 37200b57cec5SDimitry Andric // Navigate to relevant type information. 37210b57cec5SDimitry Andric const BlockPointerType *CPT = nullptr; 37220b57cec5SDimitry Andric 37230b57cec5SDimitry Andric if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { 37240b57cec5SDimitry Andric CPT = DRE->getType()->getAs<BlockPointerType>(); 37250b57cec5SDimitry Andric } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { 37260b57cec5SDimitry Andric CPT = MExpr->getType()->getAs<BlockPointerType>(); 37270b57cec5SDimitry Andric } 37280b57cec5SDimitry Andric else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) { 37290b57cec5SDimitry Andric return SynthesizeBlockCall(Exp, PRE->getSubExpr()); 37300b57cec5SDimitry Andric } 37310b57cec5SDimitry Andric else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 37320b57cec5SDimitry Andric CPT = IEXPR->getType()->getAs<BlockPointerType>(); 37330b57cec5SDimitry Andric else if (const ConditionalOperator *CEXPR = 37340b57cec5SDimitry Andric dyn_cast<ConditionalOperator>(BlockExp)) { 37350b57cec5SDimitry Andric Expr *LHSExp = CEXPR->getLHS(); 37360b57cec5SDimitry Andric Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp); 37370b57cec5SDimitry Andric Expr *RHSExp = CEXPR->getRHS(); 37380b57cec5SDimitry Andric Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); 37390b57cec5SDimitry Andric Expr *CONDExp = CEXPR->getCond(); 3740fe6060f1SDimitry Andric ConditionalOperator *CondExpr = new (Context) ConditionalOperator( 3741fe6060f1SDimitry Andric CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(), 3742fe6060f1SDimitry Andric cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary); 37430b57cec5SDimitry Andric return CondExpr; 37440b57cec5SDimitry Andric } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { 37450b57cec5SDimitry Andric CPT = IRE->getType()->getAs<BlockPointerType>(); 37460b57cec5SDimitry Andric } else if (const PseudoObjectExpr *POE 37470b57cec5SDimitry Andric = dyn_cast<PseudoObjectExpr>(BlockExp)) { 37480b57cec5SDimitry Andric CPT = POE->getType()->castAs<BlockPointerType>(); 37490b57cec5SDimitry Andric } else { 37500b57cec5SDimitry Andric assert(false && "RewriteBlockClass: Bad type"); 37510b57cec5SDimitry Andric } 37520b57cec5SDimitry Andric assert(CPT && "RewriteBlockClass: Bad type"); 37530b57cec5SDimitry Andric const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); 37540b57cec5SDimitry Andric assert(FT && "RewriteBlockClass: Bad type"); 37550b57cec5SDimitry Andric const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 37560b57cec5SDimitry Andric // FTP will be null for closures that don't take arguments. 37570b57cec5SDimitry Andric 3758*5f757f3fSDimitry Andric RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 37590b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 37600b57cec5SDimitry Andric &Context->Idents.get("__block_impl")); 37610b57cec5SDimitry Andric QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); 37620b57cec5SDimitry Andric 37630b57cec5SDimitry Andric // Generate a funky cast. 37640b57cec5SDimitry Andric SmallVector<QualType, 8> ArgTypes; 37650b57cec5SDimitry Andric 37660b57cec5SDimitry Andric // Push the block argument type. 37670b57cec5SDimitry Andric ArgTypes.push_back(PtrBlock); 37680b57cec5SDimitry Andric if (FTP) { 37690b57cec5SDimitry Andric for (auto &I : FTP->param_types()) { 37700b57cec5SDimitry Andric QualType t = I; 37710b57cec5SDimitry Andric // Make sure we convert "t (^)(...)" to "t (*)(...)". 37720b57cec5SDimitry Andric if (!convertBlockPointerToFunctionPointer(t)) 37730b57cec5SDimitry Andric convertToUnqualifiedObjCType(t); 37740b57cec5SDimitry Andric ArgTypes.push_back(t); 37750b57cec5SDimitry Andric } 37760b57cec5SDimitry Andric } 37770b57cec5SDimitry Andric // Now do the pointer to function cast. 37780b57cec5SDimitry Andric QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes); 37790b57cec5SDimitry Andric 37800b57cec5SDimitry Andric PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); 37810b57cec5SDimitry Andric 37820b57cec5SDimitry Andric CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock, 37830b57cec5SDimitry Andric CK_BitCast, 37840b57cec5SDimitry Andric const_cast<Expr*>(BlockExp)); 37850b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 37860b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 37870b57cec5SDimitry Andric BlkCast); 37880b57cec5SDimitry Andric //PE->dump(); 37890b57cec5SDimitry Andric 37900b57cec5SDimitry Andric FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 37910b57cec5SDimitry Andric SourceLocation(), 37920b57cec5SDimitry Andric &Context->Idents.get("FuncPtr"), 37930b57cec5SDimitry Andric Context->VoidPtrTy, nullptr, 37940b57cec5SDimitry Andric /*BitWidth=*/nullptr, /*Mutable=*/true, 37950b57cec5SDimitry Andric ICIS_NoInit); 37960b57cec5SDimitry Andric MemberExpr *ME = MemberExpr::CreateImplicit( 37970b57cec5SDimitry Andric *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); 37980b57cec5SDimitry Andric 37990b57cec5SDimitry Andric CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, 38000b57cec5SDimitry Andric CK_BitCast, ME); 38010b57cec5SDimitry Andric PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); 38020b57cec5SDimitry Andric 38030b57cec5SDimitry Andric SmallVector<Expr*, 8> BlkExprs; 38040b57cec5SDimitry Andric // Add the implicit argument. 38050b57cec5SDimitry Andric BlkExprs.push_back(BlkCast); 38060b57cec5SDimitry Andric // Add the user arguments. 38070b57cec5SDimitry Andric for (CallExpr::arg_iterator I = Exp->arg_begin(), 38080b57cec5SDimitry Andric E = Exp->arg_end(); I != E; ++I) { 38090b57cec5SDimitry Andric BlkExprs.push_back(*I); 38100b57cec5SDimitry Andric } 3811e8d8bef9SDimitry Andric CallExpr *CE = 3812fe6060f1SDimitry Andric CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue, 3813e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 38140b57cec5SDimitry Andric return CE; 38150b57cec5SDimitry Andric } 38160b57cec5SDimitry Andric 38170b57cec5SDimitry Andric // We need to return the rewritten expression to handle cases where the 38180b57cec5SDimitry Andric // BlockDeclRefExpr is embedded in another expression being rewritten. 38190b57cec5SDimitry Andric // For example: 38200b57cec5SDimitry Andric // 38210b57cec5SDimitry Andric // int main() { 38220b57cec5SDimitry Andric // __block Foo *f; 38230b57cec5SDimitry Andric // __block int i; 38240b57cec5SDimitry Andric // 38250b57cec5SDimitry Andric // void (^myblock)() = ^() { 38260b57cec5SDimitry Andric // [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten). 38270b57cec5SDimitry Andric // i = 77; 38280b57cec5SDimitry Andric // }; 38290b57cec5SDimitry Andric //} 38300b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { 38310b57cec5SDimitry Andric // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 38320b57cec5SDimitry Andric // for each DeclRefExp where BYREFVAR is name of the variable. 38330b57cec5SDimitry Andric ValueDecl *VD = DeclRefExp->getDecl(); 38340b57cec5SDimitry Andric bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() || 38350b57cec5SDimitry Andric HasLocalVariableExternalStorage(DeclRefExp->getDecl()); 38360b57cec5SDimitry Andric 38370b57cec5SDimitry Andric FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 38380b57cec5SDimitry Andric SourceLocation(), 38390b57cec5SDimitry Andric &Context->Idents.get("__forwarding"), 38400b57cec5SDimitry Andric Context->VoidPtrTy, nullptr, 38410b57cec5SDimitry Andric /*BitWidth=*/nullptr, /*Mutable=*/true, 38420b57cec5SDimitry Andric ICIS_NoInit); 38430b57cec5SDimitry Andric MemberExpr *ME = 38440b57cec5SDimitry Andric MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD, 38450b57cec5SDimitry Andric FD->getType(), VK_LValue, OK_Ordinary); 38460b57cec5SDimitry Andric 38470b57cec5SDimitry Andric StringRef Name = VD->getName(); 38480b57cec5SDimitry Andric FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), 38490b57cec5SDimitry Andric &Context->Idents.get(Name), 38500b57cec5SDimitry Andric Context->VoidPtrTy, nullptr, 38510b57cec5SDimitry Andric /*BitWidth=*/nullptr, /*Mutable=*/true, 38520b57cec5SDimitry Andric ICIS_NoInit); 38530b57cec5SDimitry Andric ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(), 38540b57cec5SDimitry Andric VK_LValue, OK_Ordinary); 38550b57cec5SDimitry Andric 38560b57cec5SDimitry Andric // Need parens to enforce precedence. 38570b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 38580b57cec5SDimitry Andric DeclRefExp->getExprLoc(), 38590b57cec5SDimitry Andric ME); 38600b57cec5SDimitry Andric ReplaceStmt(DeclRefExp, PE); 38610b57cec5SDimitry Andric return PE; 38620b57cec5SDimitry Andric } 38630b57cec5SDimitry Andric 38640b57cec5SDimitry Andric // Rewrites the imported local variable V with external storage 38650b57cec5SDimitry Andric // (static, extern, etc.) as *V 38660b57cec5SDimitry Andric // 38670b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { 38680b57cec5SDimitry Andric ValueDecl *VD = DRE->getDecl(); 38690b57cec5SDimitry Andric if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 38700b57cec5SDimitry Andric if (!ImportedLocalExternalDecls.count(Var)) 38710b57cec5SDimitry Andric return DRE; 38725ffd83dbSDimitry Andric Expr *Exp = UnaryOperator::Create( 38735ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(), 38745ffd83dbSDimitry Andric VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride()); 38750b57cec5SDimitry Andric // Need parens to enforce precedence. 38760b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 38770b57cec5SDimitry Andric Exp); 38780b57cec5SDimitry Andric ReplaceStmt(DRE, PE); 38790b57cec5SDimitry Andric return PE; 38800b57cec5SDimitry Andric } 38810b57cec5SDimitry Andric 38820b57cec5SDimitry Andric void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { 38830b57cec5SDimitry Andric SourceLocation LocStart = CE->getLParenLoc(); 38840b57cec5SDimitry Andric SourceLocation LocEnd = CE->getRParenLoc(); 38850b57cec5SDimitry Andric 38860b57cec5SDimitry Andric // Need to avoid trying to rewrite synthesized casts. 38870b57cec5SDimitry Andric if (LocStart.isInvalid()) 38880b57cec5SDimitry Andric return; 38890b57cec5SDimitry Andric // Need to avoid trying to rewrite casts contained in macros. 38900b57cec5SDimitry Andric if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) 38910b57cec5SDimitry Andric return; 38920b57cec5SDimitry Andric 38930b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 38940b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 38950b57cec5SDimitry Andric QualType QT = CE->getType(); 38960b57cec5SDimitry Andric const Type* TypePtr = QT->getAs<Type>(); 38970b57cec5SDimitry Andric if (isa<TypeOfExprType>(TypePtr)) { 38980b57cec5SDimitry Andric const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 38990b57cec5SDimitry Andric QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 39000b57cec5SDimitry Andric std::string TypeAsString = "("; 39010b57cec5SDimitry Andric RewriteBlockPointerType(TypeAsString, QT); 39020b57cec5SDimitry Andric TypeAsString += ")"; 39030b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); 39040b57cec5SDimitry Andric return; 39050b57cec5SDimitry Andric } 39060b57cec5SDimitry Andric // advance the location to startArgList. 39070b57cec5SDimitry Andric const char *argPtr = startBuf; 39080b57cec5SDimitry Andric 39090b57cec5SDimitry Andric while (*argPtr++ && (argPtr < endBuf)) { 39100b57cec5SDimitry Andric switch (*argPtr) { 39110b57cec5SDimitry Andric case '^': 39120b57cec5SDimitry Andric // Replace the '^' with '*'. 39130b57cec5SDimitry Andric LocStart = LocStart.getLocWithOffset(argPtr-startBuf); 39140b57cec5SDimitry Andric ReplaceText(LocStart, 1, "*"); 39150b57cec5SDimitry Andric break; 39160b57cec5SDimitry Andric } 39170b57cec5SDimitry Andric } 39180b57cec5SDimitry Andric } 39190b57cec5SDimitry Andric 39200b57cec5SDimitry Andric void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { 39210b57cec5SDimitry Andric SourceLocation DeclLoc = FD->getLocation(); 39220b57cec5SDimitry Andric unsigned parenCount = 0; 39230b57cec5SDimitry Andric 39240b57cec5SDimitry Andric // We have 1 or more arguments that have closure pointers. 39250b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(DeclLoc); 39260b57cec5SDimitry Andric const char *startArgList = strchr(startBuf, '('); 39270b57cec5SDimitry Andric 39280b57cec5SDimitry Andric assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); 39290b57cec5SDimitry Andric 39300b57cec5SDimitry Andric parenCount++; 39310b57cec5SDimitry Andric // advance the location to startArgList. 39320b57cec5SDimitry Andric DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf); 39330b57cec5SDimitry Andric assert((DeclLoc.isValid()) && "Invalid DeclLoc"); 39340b57cec5SDimitry Andric 39350b57cec5SDimitry Andric const char *argPtr = startArgList; 39360b57cec5SDimitry Andric 39370b57cec5SDimitry Andric while (*argPtr++ && parenCount) { 39380b57cec5SDimitry Andric switch (*argPtr) { 39390b57cec5SDimitry Andric case '^': 39400b57cec5SDimitry Andric // Replace the '^' with '*'. 39410b57cec5SDimitry Andric DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList); 39420b57cec5SDimitry Andric ReplaceText(DeclLoc, 1, "*"); 39430b57cec5SDimitry Andric break; 39440b57cec5SDimitry Andric case '(': 39450b57cec5SDimitry Andric parenCount++; 39460b57cec5SDimitry Andric break; 39470b57cec5SDimitry Andric case ')': 39480b57cec5SDimitry Andric parenCount--; 39490b57cec5SDimitry Andric break; 39500b57cec5SDimitry Andric } 39510b57cec5SDimitry Andric } 39520b57cec5SDimitry Andric } 39530b57cec5SDimitry Andric 39540b57cec5SDimitry Andric bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { 39550b57cec5SDimitry Andric const FunctionProtoType *FTP; 39560b57cec5SDimitry Andric const PointerType *PT = QT->getAs<PointerType>(); 39570b57cec5SDimitry Andric if (PT) { 39580b57cec5SDimitry Andric FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 39590b57cec5SDimitry Andric } else { 39600b57cec5SDimitry Andric const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 39610b57cec5SDimitry Andric assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 39620b57cec5SDimitry Andric FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 39630b57cec5SDimitry Andric } 39640b57cec5SDimitry Andric if (FTP) { 39650b57cec5SDimitry Andric for (const auto &I : FTP->param_types()) 39660b57cec5SDimitry Andric if (isTopLevelBlockPointerType(I)) 39670b57cec5SDimitry Andric return true; 39680b57cec5SDimitry Andric } 39690b57cec5SDimitry Andric return false; 39700b57cec5SDimitry Andric } 39710b57cec5SDimitry Andric 39720b57cec5SDimitry Andric bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) { 39730b57cec5SDimitry Andric const FunctionProtoType *FTP; 39740b57cec5SDimitry Andric const PointerType *PT = QT->getAs<PointerType>(); 39750b57cec5SDimitry Andric if (PT) { 39760b57cec5SDimitry Andric FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 39770b57cec5SDimitry Andric } else { 39780b57cec5SDimitry Andric const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 39790b57cec5SDimitry Andric assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 39800b57cec5SDimitry Andric FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 39810b57cec5SDimitry Andric } 39820b57cec5SDimitry Andric if (FTP) { 39830b57cec5SDimitry Andric for (const auto &I : FTP->param_types()) { 39840b57cec5SDimitry Andric if (I->isObjCQualifiedIdType()) 39850b57cec5SDimitry Andric return true; 39860b57cec5SDimitry Andric if (I->isObjCObjectPointerType() && 39870b57cec5SDimitry Andric I->getPointeeType()->isObjCQualifiedInterfaceType()) 39880b57cec5SDimitry Andric return true; 39890b57cec5SDimitry Andric } 39900b57cec5SDimitry Andric 39910b57cec5SDimitry Andric } 39920b57cec5SDimitry Andric return false; 39930b57cec5SDimitry Andric } 39940b57cec5SDimitry Andric 39950b57cec5SDimitry Andric void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen, 39960b57cec5SDimitry Andric const char *&RParen) { 39970b57cec5SDimitry Andric const char *argPtr = strchr(Name, '('); 39980b57cec5SDimitry Andric assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); 39990b57cec5SDimitry Andric 40000b57cec5SDimitry Andric LParen = argPtr; // output the start. 40010b57cec5SDimitry Andric argPtr++; // skip past the left paren. 40020b57cec5SDimitry Andric unsigned parenCount = 1; 40030b57cec5SDimitry Andric 40040b57cec5SDimitry Andric while (*argPtr && parenCount) { 40050b57cec5SDimitry Andric switch (*argPtr) { 40060b57cec5SDimitry Andric case '(': parenCount++; break; 40070b57cec5SDimitry Andric case ')': parenCount--; break; 40080b57cec5SDimitry Andric default: break; 40090b57cec5SDimitry Andric } 40100b57cec5SDimitry Andric if (parenCount) argPtr++; 40110b57cec5SDimitry Andric } 40120b57cec5SDimitry Andric assert((*argPtr == ')') && "Rewriter fuzzy parser confused"); 40130b57cec5SDimitry Andric RParen = argPtr; // output the end 40140b57cec5SDimitry Andric } 40150b57cec5SDimitry Andric 40160b57cec5SDimitry Andric void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { 40170b57cec5SDimitry Andric if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 40180b57cec5SDimitry Andric RewriteBlockPointerFunctionArgs(FD); 40190b57cec5SDimitry Andric return; 40200b57cec5SDimitry Andric } 40210b57cec5SDimitry Andric // Handle Variables and Typedefs. 40220b57cec5SDimitry Andric SourceLocation DeclLoc = ND->getLocation(); 40230b57cec5SDimitry Andric QualType DeclT; 40240b57cec5SDimitry Andric if (VarDecl *VD = dyn_cast<VarDecl>(ND)) 40250b57cec5SDimitry Andric DeclT = VD->getType(); 40260b57cec5SDimitry Andric else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND)) 40270b57cec5SDimitry Andric DeclT = TDD->getUnderlyingType(); 40280b57cec5SDimitry Andric else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) 40290b57cec5SDimitry Andric DeclT = FD->getType(); 40300b57cec5SDimitry Andric else 40310b57cec5SDimitry Andric llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled"); 40320b57cec5SDimitry Andric 40330b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(DeclLoc); 40340b57cec5SDimitry Andric const char *endBuf = startBuf; 40350b57cec5SDimitry Andric // scan backward (from the decl location) for the end of the previous decl. 40360b57cec5SDimitry Andric while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) 40370b57cec5SDimitry Andric startBuf--; 40380b57cec5SDimitry Andric SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf); 40390b57cec5SDimitry Andric std::string buf; 40400b57cec5SDimitry Andric unsigned OrigLength=0; 40410b57cec5SDimitry Andric // *startBuf != '^' if we are dealing with a pointer to function that 40420b57cec5SDimitry Andric // may take block argument types (which will be handled below). 40430b57cec5SDimitry Andric if (*startBuf == '^') { 40440b57cec5SDimitry Andric // Replace the '^' with '*', computing a negative offset. 40450b57cec5SDimitry Andric buf = '*'; 40460b57cec5SDimitry Andric startBuf++; 40470b57cec5SDimitry Andric OrigLength++; 40480b57cec5SDimitry Andric } 40490b57cec5SDimitry Andric while (*startBuf != ')') { 40500b57cec5SDimitry Andric buf += *startBuf; 40510b57cec5SDimitry Andric startBuf++; 40520b57cec5SDimitry Andric OrigLength++; 40530b57cec5SDimitry Andric } 40540b57cec5SDimitry Andric buf += ')'; 40550b57cec5SDimitry Andric OrigLength++; 40560b57cec5SDimitry Andric 40570b57cec5SDimitry Andric if (PointerTypeTakesAnyBlockArguments(DeclT) || 40580b57cec5SDimitry Andric PointerTypeTakesAnyObjCQualifiedType(DeclT)) { 40590b57cec5SDimitry Andric // Replace the '^' with '*' for arguments. 40600b57cec5SDimitry Andric // Replace id<P> with id/*<>*/ 40610b57cec5SDimitry Andric DeclLoc = ND->getLocation(); 40620b57cec5SDimitry Andric startBuf = SM->getCharacterData(DeclLoc); 40630b57cec5SDimitry Andric const char *argListBegin, *argListEnd; 40640b57cec5SDimitry Andric GetExtentOfArgList(startBuf, argListBegin, argListEnd); 40650b57cec5SDimitry Andric while (argListBegin < argListEnd) { 40660b57cec5SDimitry Andric if (*argListBegin == '^') 40670b57cec5SDimitry Andric buf += '*'; 40680b57cec5SDimitry Andric else if (*argListBegin == '<') { 40690b57cec5SDimitry Andric buf += "/*"; 40700b57cec5SDimitry Andric buf += *argListBegin++; 40710b57cec5SDimitry Andric OrigLength++; 40720b57cec5SDimitry Andric while (*argListBegin != '>') { 40730b57cec5SDimitry Andric buf += *argListBegin++; 40740b57cec5SDimitry Andric OrigLength++; 40750b57cec5SDimitry Andric } 40760b57cec5SDimitry Andric buf += *argListBegin; 40770b57cec5SDimitry Andric buf += "*/"; 40780b57cec5SDimitry Andric } 40790b57cec5SDimitry Andric else 40800b57cec5SDimitry Andric buf += *argListBegin; 40810b57cec5SDimitry Andric argListBegin++; 40820b57cec5SDimitry Andric OrigLength++; 40830b57cec5SDimitry Andric } 40840b57cec5SDimitry Andric buf += ')'; 40850b57cec5SDimitry Andric OrigLength++; 40860b57cec5SDimitry Andric } 40870b57cec5SDimitry Andric ReplaceText(Start, OrigLength, buf); 40880b57cec5SDimitry Andric } 40890b57cec5SDimitry Andric 40900b57cec5SDimitry Andric /// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: 40910b57cec5SDimitry Andric /// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, 40920b57cec5SDimitry Andric /// struct Block_byref_id_object *src) { 40930b57cec5SDimitry Andric /// _Block_object_assign (&_dest->object, _src->object, 40940b57cec5SDimitry Andric /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 40950b57cec5SDimitry Andric /// [|BLOCK_FIELD_IS_WEAK]) // object 40960b57cec5SDimitry Andric /// _Block_object_assign(&_dest->object, _src->object, 40970b57cec5SDimitry Andric /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 40980b57cec5SDimitry Andric /// [|BLOCK_FIELD_IS_WEAK]) // block 40990b57cec5SDimitry Andric /// } 41000b57cec5SDimitry Andric /// And: 41010b57cec5SDimitry Andric /// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { 41020b57cec5SDimitry Andric /// _Block_object_dispose(_src->object, 41030b57cec5SDimitry Andric /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 41040b57cec5SDimitry Andric /// [|BLOCK_FIELD_IS_WEAK]) // object 41050b57cec5SDimitry Andric /// _Block_object_dispose(_src->object, 41060b57cec5SDimitry Andric /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 41070b57cec5SDimitry Andric /// [|BLOCK_FIELD_IS_WEAK]) // block 41080b57cec5SDimitry Andric /// } 41090b57cec5SDimitry Andric 41100b57cec5SDimitry Andric std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, 41110b57cec5SDimitry Andric int flag) { 41120b57cec5SDimitry Andric std::string S; 41130b57cec5SDimitry Andric if (CopyDestroyCache.count(flag)) 41140b57cec5SDimitry Andric return S; 41150b57cec5SDimitry Andric CopyDestroyCache.insert(flag); 41160b57cec5SDimitry Andric S = "static void __Block_byref_id_object_copy_"; 41170b57cec5SDimitry Andric S += utostr(flag); 41180b57cec5SDimitry Andric S += "(void *dst, void *src) {\n"; 41190b57cec5SDimitry Andric 41200b57cec5SDimitry Andric // offset into the object pointer is computed as: 41210b57cec5SDimitry Andric // void * + void* + int + int + void* + void * 41220b57cec5SDimitry Andric unsigned IntSize = 41230b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 41240b57cec5SDimitry Andric unsigned VoidPtrSize = 41250b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); 41260b57cec5SDimitry Andric 41270b57cec5SDimitry Andric unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth(); 41280b57cec5SDimitry Andric S += " _Block_object_assign((char*)dst + "; 41290b57cec5SDimitry Andric S += utostr(offset); 41300b57cec5SDimitry Andric S += ", *(void * *) ((char*)src + "; 41310b57cec5SDimitry Andric S += utostr(offset); 41320b57cec5SDimitry Andric S += "), "; 41330b57cec5SDimitry Andric S += utostr(flag); 41340b57cec5SDimitry Andric S += ");\n}\n"; 41350b57cec5SDimitry Andric 41360b57cec5SDimitry Andric S += "static void __Block_byref_id_object_dispose_"; 41370b57cec5SDimitry Andric S += utostr(flag); 41380b57cec5SDimitry Andric S += "(void *src) {\n"; 41390b57cec5SDimitry Andric S += " _Block_object_dispose(*(void * *) ((char*)src + "; 41400b57cec5SDimitry Andric S += utostr(offset); 41410b57cec5SDimitry Andric S += "), "; 41420b57cec5SDimitry Andric S += utostr(flag); 41430b57cec5SDimitry Andric S += ");\n}\n"; 41440b57cec5SDimitry Andric return S; 41450b57cec5SDimitry Andric } 41460b57cec5SDimitry Andric 41470b57cec5SDimitry Andric /// RewriteByRefVar - For each __block typex ND variable this routine transforms 41480b57cec5SDimitry Andric /// the declaration into: 41490b57cec5SDimitry Andric /// struct __Block_byref_ND { 41500b57cec5SDimitry Andric /// void *__isa; // NULL for everything except __weak pointers 41510b57cec5SDimitry Andric /// struct __Block_byref_ND *__forwarding; 41520b57cec5SDimitry Andric /// int32_t __flags; 41530b57cec5SDimitry Andric /// int32_t __size; 41540b57cec5SDimitry Andric /// void *__Block_byref_id_object_copy; // If variable is __block ObjC object 41550b57cec5SDimitry Andric /// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object 41560b57cec5SDimitry Andric /// typex ND; 41570b57cec5SDimitry Andric /// }; 41580b57cec5SDimitry Andric /// 41590b57cec5SDimitry Andric /// It then replaces declaration of ND variable with: 41600b57cec5SDimitry Andric /// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 41610b57cec5SDimitry Andric /// __size=sizeof(struct __Block_byref_ND), 41620b57cec5SDimitry Andric /// ND=initializer-if-any}; 41630b57cec5SDimitry Andric /// 41640b57cec5SDimitry Andric /// 41650b57cec5SDimitry Andric void RewriteObjC::RewriteByRefVar(VarDecl *ND) { 41660b57cec5SDimitry Andric // Insert declaration for the function in which block literal is 41670b57cec5SDimitry Andric // used. 41680b57cec5SDimitry Andric if (CurFunctionDeclToDeclareForBlock) 41690b57cec5SDimitry Andric RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 41700b57cec5SDimitry Andric int flag = 0; 41710b57cec5SDimitry Andric int isa = 0; 41720b57cec5SDimitry Andric SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 41730b57cec5SDimitry Andric if (DeclLoc.isInvalid()) 41740b57cec5SDimitry Andric // If type location is missing, it is because of missing type (a warning). 41750b57cec5SDimitry Andric // Use variable's location which is good for this case. 41760b57cec5SDimitry Andric DeclLoc = ND->getLocation(); 41770b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(DeclLoc); 41780b57cec5SDimitry Andric SourceLocation X = ND->getEndLoc(); 41790b57cec5SDimitry Andric X = SM->getExpansionLoc(X); 41800b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(X); 41810b57cec5SDimitry Andric std::string Name(ND->getNameAsString()); 41820b57cec5SDimitry Andric std::string ByrefType; 41830b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND, true); 41840b57cec5SDimitry Andric ByrefType += " {\n"; 41850b57cec5SDimitry Andric ByrefType += " void *__isa;\n"; 41860b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND); 41870b57cec5SDimitry Andric ByrefType += " *__forwarding;\n"; 41880b57cec5SDimitry Andric ByrefType += " int __flags;\n"; 41890b57cec5SDimitry Andric ByrefType += " int __size;\n"; 41900b57cec5SDimitry Andric // Add void *__Block_byref_id_object_copy; 41910b57cec5SDimitry Andric // void *__Block_byref_id_object_dispose; if needed. 41920b57cec5SDimitry Andric QualType Ty = ND->getType(); 41930b57cec5SDimitry Andric bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND); 41940b57cec5SDimitry Andric if (HasCopyAndDispose) { 41950b57cec5SDimitry Andric ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; 41960b57cec5SDimitry Andric ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; 41970b57cec5SDimitry Andric } 41980b57cec5SDimitry Andric 41990b57cec5SDimitry Andric QualType T = Ty; 42000b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(T); 42010b57cec5SDimitry Andric T.getAsStringInternal(Name, Context->getPrintingPolicy()); 42020b57cec5SDimitry Andric 42030b57cec5SDimitry Andric ByrefType += " " + Name + ";\n"; 42040b57cec5SDimitry Andric ByrefType += "};\n"; 42050b57cec5SDimitry Andric // Insert this type in global scope. It is needed by helper function. 42060b57cec5SDimitry Andric SourceLocation FunLocStart; 42070b57cec5SDimitry Andric if (CurFunctionDef) 42080b57cec5SDimitry Andric FunLocStart = CurFunctionDef->getTypeSpecStartLoc(); 42090b57cec5SDimitry Andric else { 42100b57cec5SDimitry Andric assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); 42110b57cec5SDimitry Andric FunLocStart = CurMethodDef->getBeginLoc(); 42120b57cec5SDimitry Andric } 42130b57cec5SDimitry Andric InsertText(FunLocStart, ByrefType); 42140b57cec5SDimitry Andric if (Ty.isObjCGCWeak()) { 42150b57cec5SDimitry Andric flag |= BLOCK_FIELD_IS_WEAK; 42160b57cec5SDimitry Andric isa = 1; 42170b57cec5SDimitry Andric } 42180b57cec5SDimitry Andric 42190b57cec5SDimitry Andric if (HasCopyAndDispose) { 42200b57cec5SDimitry Andric flag = BLOCK_BYREF_CALLER; 42210b57cec5SDimitry Andric QualType Ty = ND->getType(); 42220b57cec5SDimitry Andric // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. 42230b57cec5SDimitry Andric if (Ty->isBlockPointerType()) 42240b57cec5SDimitry Andric flag |= BLOCK_FIELD_IS_BLOCK; 42250b57cec5SDimitry Andric else 42260b57cec5SDimitry Andric flag |= BLOCK_FIELD_IS_OBJECT; 42270b57cec5SDimitry Andric std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); 42280b57cec5SDimitry Andric if (!HF.empty()) 42290b57cec5SDimitry Andric InsertText(FunLocStart, HF); 42300b57cec5SDimitry Andric } 42310b57cec5SDimitry Andric 42320b57cec5SDimitry Andric // struct __Block_byref_ND ND = 42330b57cec5SDimitry Andric // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 42340b57cec5SDimitry Andric // initializer-if-any}; 42350b57cec5SDimitry Andric bool hasInit = (ND->getInit() != nullptr); 42360b57cec5SDimitry Andric unsigned flags = 0; 42370b57cec5SDimitry Andric if (HasCopyAndDispose) 42380b57cec5SDimitry Andric flags |= BLOCK_HAS_COPY_DISPOSE; 42390b57cec5SDimitry Andric Name = ND->getNameAsString(); 42400b57cec5SDimitry Andric ByrefType.clear(); 42410b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND); 42420b57cec5SDimitry Andric std::string ForwardingCastType("("); 42430b57cec5SDimitry Andric ForwardingCastType += ByrefType + " *)"; 42440b57cec5SDimitry Andric if (!hasInit) { 42450b57cec5SDimitry Andric ByrefType += " " + Name + " = {(void*)"; 42460b57cec5SDimitry Andric ByrefType += utostr(isa); 42470b57cec5SDimitry Andric ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 42480b57cec5SDimitry Andric ByrefType += utostr(flags); 42490b57cec5SDimitry Andric ByrefType += ", "; 42500b57cec5SDimitry Andric ByrefType += "sizeof("; 42510b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND); 42520b57cec5SDimitry Andric ByrefType += ")"; 42530b57cec5SDimitry Andric if (HasCopyAndDispose) { 42540b57cec5SDimitry Andric ByrefType += ", __Block_byref_id_object_copy_"; 42550b57cec5SDimitry Andric ByrefType += utostr(flag); 42560b57cec5SDimitry Andric ByrefType += ", __Block_byref_id_object_dispose_"; 42570b57cec5SDimitry Andric ByrefType += utostr(flag); 42580b57cec5SDimitry Andric } 42590b57cec5SDimitry Andric ByrefType += "};\n"; 42600b57cec5SDimitry Andric unsigned nameSize = Name.size(); 42610b57cec5SDimitry Andric // for block or function pointer declaration. Name is already 42620b57cec5SDimitry Andric // part of the declaration. 42630b57cec5SDimitry Andric if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) 42640b57cec5SDimitry Andric nameSize = 1; 42650b57cec5SDimitry Andric ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType); 42660b57cec5SDimitry Andric } 42670b57cec5SDimitry Andric else { 42680b57cec5SDimitry Andric SourceLocation startLoc; 42690b57cec5SDimitry Andric Expr *E = ND->getInit(); 42700b57cec5SDimitry Andric if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 42710b57cec5SDimitry Andric startLoc = ECE->getLParenLoc(); 42720b57cec5SDimitry Andric else 42730b57cec5SDimitry Andric startLoc = E->getBeginLoc(); 42740b57cec5SDimitry Andric startLoc = SM->getExpansionLoc(startLoc); 42750b57cec5SDimitry Andric endBuf = SM->getCharacterData(startLoc); 42760b57cec5SDimitry Andric ByrefType += " " + Name; 42770b57cec5SDimitry Andric ByrefType += " = {(void*)"; 42780b57cec5SDimitry Andric ByrefType += utostr(isa); 42790b57cec5SDimitry Andric ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 42800b57cec5SDimitry Andric ByrefType += utostr(flags); 42810b57cec5SDimitry Andric ByrefType += ", "; 42820b57cec5SDimitry Andric ByrefType += "sizeof("; 42830b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND); 42840b57cec5SDimitry Andric ByrefType += "), "; 42850b57cec5SDimitry Andric if (HasCopyAndDispose) { 42860b57cec5SDimitry Andric ByrefType += "__Block_byref_id_object_copy_"; 42870b57cec5SDimitry Andric ByrefType += utostr(flag); 42880b57cec5SDimitry Andric ByrefType += ", __Block_byref_id_object_dispose_"; 42890b57cec5SDimitry Andric ByrefType += utostr(flag); 42900b57cec5SDimitry Andric ByrefType += ", "; 42910b57cec5SDimitry Andric } 42920b57cec5SDimitry Andric ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); 42930b57cec5SDimitry Andric 42940b57cec5SDimitry Andric // Complete the newly synthesized compound expression by inserting a right 42950b57cec5SDimitry Andric // curly brace before the end of the declaration. 42960b57cec5SDimitry Andric // FIXME: This approach avoids rewriting the initializer expression. It 42970b57cec5SDimitry Andric // also assumes there is only one declarator. For example, the following 42980b57cec5SDimitry Andric // isn't currently supported by this routine (in general): 42990b57cec5SDimitry Andric // 43000b57cec5SDimitry Andric // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37; 43010b57cec5SDimitry Andric // 43020b57cec5SDimitry Andric const char *startInitializerBuf = SM->getCharacterData(startLoc); 43030b57cec5SDimitry Andric const char *semiBuf = strchr(startInitializerBuf, ';'); 43040b57cec5SDimitry Andric assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'"); 43050b57cec5SDimitry Andric SourceLocation semiLoc = 43060b57cec5SDimitry Andric startLoc.getLocWithOffset(semiBuf-startInitializerBuf); 43070b57cec5SDimitry Andric 43080b57cec5SDimitry Andric InsertText(semiLoc, "}"); 43090b57cec5SDimitry Andric } 43100b57cec5SDimitry Andric } 43110b57cec5SDimitry Andric 43120b57cec5SDimitry Andric void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { 43130b57cec5SDimitry Andric // Add initializers for any closure decl refs. 43140b57cec5SDimitry Andric GetBlockDeclRefExprs(Exp->getBody()); 43150b57cec5SDimitry Andric if (BlockDeclRefs.size()) { 43160b57cec5SDimitry Andric // Unique all "by copy" declarations. 43170b57cec5SDimitry Andric for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 43180b57cec5SDimitry Andric if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 43190b57cec5SDimitry Andric if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 43200b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 43210b57cec5SDimitry Andric BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); 43220b57cec5SDimitry Andric } 43230b57cec5SDimitry Andric } 43240b57cec5SDimitry Andric // Unique all "by ref" declarations. 43250b57cec5SDimitry Andric for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 43260b57cec5SDimitry Andric if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 43270b57cec5SDimitry Andric if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 43280b57cec5SDimitry Andric BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 43290b57cec5SDimitry Andric BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); 43300b57cec5SDimitry Andric } 43310b57cec5SDimitry Andric } 43320b57cec5SDimitry Andric // Find any imported blocks...they will need special attention. 43330b57cec5SDimitry Andric for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 43340b57cec5SDimitry Andric if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 43350b57cec5SDimitry Andric BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 43360b57cec5SDimitry Andric BlockDeclRefs[i]->getType()->isBlockPointerType()) 43370b57cec5SDimitry Andric ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); 43380b57cec5SDimitry Andric } 43390b57cec5SDimitry Andric } 43400b57cec5SDimitry Andric 43410b57cec5SDimitry Andric FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) { 43420b57cec5SDimitry Andric IdentifierInfo *ID = &Context->Idents.get(name); 43430b57cec5SDimitry Andric QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); 43440b57cec5SDimitry Andric return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), 43450b57cec5SDimitry Andric SourceLocation(), ID, FType, nullptr, SC_Extern, 43460b57cec5SDimitry Andric false, false); 43470b57cec5SDimitry Andric } 43480b57cec5SDimitry Andric 43490b57cec5SDimitry Andric Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, 43500b57cec5SDimitry Andric const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) { 43510b57cec5SDimitry Andric const BlockDecl *block = Exp->getBlockDecl(); 43520b57cec5SDimitry Andric Blocks.push_back(Exp); 43530b57cec5SDimitry Andric 43540b57cec5SDimitry Andric CollectBlockDeclRefInfo(Exp); 43550b57cec5SDimitry Andric 43560b57cec5SDimitry Andric // Add inner imported variables now used in current block. 43570b57cec5SDimitry Andric int countOfInnerDecls = 0; 43580b57cec5SDimitry Andric if (!InnerBlockDeclRefs.empty()) { 43590b57cec5SDimitry Andric for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { 43600b57cec5SDimitry Andric DeclRefExpr *Exp = InnerBlockDeclRefs[i]; 43610b57cec5SDimitry Andric ValueDecl *VD = Exp->getDecl(); 43620b57cec5SDimitry Andric if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { 43630b57cec5SDimitry Andric // We need to save the copied-in variables in nested 43640b57cec5SDimitry Andric // blocks because it is needed at the end for some of the API generations. 43650b57cec5SDimitry Andric // See SynthesizeBlockLiterals routine. 43660b57cec5SDimitry Andric InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 43670b57cec5SDimitry Andric BlockDeclRefs.push_back(Exp); 43680b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.insert(VD); 43690b57cec5SDimitry Andric BlockByCopyDecls.push_back(VD); 43700b57cec5SDimitry Andric } 43710b57cec5SDimitry Andric if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { 43720b57cec5SDimitry Andric InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 43730b57cec5SDimitry Andric BlockDeclRefs.push_back(Exp); 43740b57cec5SDimitry Andric BlockByRefDeclsPtrSet.insert(VD); 43750b57cec5SDimitry Andric BlockByRefDecls.push_back(VD); 43760b57cec5SDimitry Andric } 43770b57cec5SDimitry Andric } 43780b57cec5SDimitry Andric // Find any imported blocks...they will need special attention. 43790b57cec5SDimitry Andric for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) 43800b57cec5SDimitry Andric if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 43810b57cec5SDimitry Andric InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 43820b57cec5SDimitry Andric InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) 43830b57cec5SDimitry Andric ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); 43840b57cec5SDimitry Andric } 43850b57cec5SDimitry Andric InnerDeclRefsCount.push_back(countOfInnerDecls); 43860b57cec5SDimitry Andric 43870b57cec5SDimitry Andric std::string FuncName; 43880b57cec5SDimitry Andric 43890b57cec5SDimitry Andric if (CurFunctionDef) 43900b57cec5SDimitry Andric FuncName = CurFunctionDef->getNameAsString(); 43910b57cec5SDimitry Andric else if (CurMethodDef) 43920b57cec5SDimitry Andric BuildUniqueMethodName(FuncName, CurMethodDef); 43930b57cec5SDimitry Andric else if (GlobalVarDecl) 43940b57cec5SDimitry Andric FuncName = std::string(GlobalVarDecl->getNameAsString()); 43950b57cec5SDimitry Andric 43960b57cec5SDimitry Andric std::string BlockNumber = utostr(Blocks.size()-1); 43970b57cec5SDimitry Andric 43980b57cec5SDimitry Andric std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber; 43990b57cec5SDimitry Andric std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; 44000b57cec5SDimitry Andric 44010b57cec5SDimitry Andric // Get a pointer to the function type so we can cast appropriately. 44020b57cec5SDimitry Andric QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType()); 44030b57cec5SDimitry Andric QualType FType = Context->getPointerType(BFT); 44040b57cec5SDimitry Andric 44050b57cec5SDimitry Andric FunctionDecl *FD; 44060b57cec5SDimitry Andric Expr *NewRep; 44070b57cec5SDimitry Andric 44080b57cec5SDimitry Andric // Simulate a constructor call... 44090b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl(Tag); 44100b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 4411fe6060f1SDimitry Andric DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation()); 44120b57cec5SDimitry Andric 44130b57cec5SDimitry Andric SmallVector<Expr*, 4> InitExprs; 44140b57cec5SDimitry Andric 44150b57cec5SDimitry Andric // Initialize the block function. 44160b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl(Func); 44170b57cec5SDimitry Andric DeclRefExpr *Arg = new (Context) DeclRefExpr( 44180b57cec5SDimitry Andric *Context, FD, false, FD->getType(), VK_LValue, SourceLocation()); 44190b57cec5SDimitry Andric CastExpr *castExpr = 44200b57cec5SDimitry Andric NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg); 44210b57cec5SDimitry Andric InitExprs.push_back(castExpr); 44220b57cec5SDimitry Andric 44230b57cec5SDimitry Andric // Initialize the block descriptor. 44240b57cec5SDimitry Andric std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; 44250b57cec5SDimitry Andric 44260b57cec5SDimitry Andric VarDecl *NewVD = VarDecl::Create( 44270b57cec5SDimitry Andric *Context, TUDecl, SourceLocation(), SourceLocation(), 44280b57cec5SDimitry Andric &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static); 44295ffd83dbSDimitry Andric UnaryOperator *DescRefExpr = UnaryOperator::Create( 44305ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), 44310b57cec5SDimitry Andric new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy, 44320b57cec5SDimitry Andric VK_LValue, SourceLocation()), 4433fe6060f1SDimitry Andric UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue, 44345ffd83dbSDimitry Andric OK_Ordinary, SourceLocation(), false, FPOptionsOverride()); 44350b57cec5SDimitry Andric InitExprs.push_back(DescRefExpr); 44360b57cec5SDimitry Andric 44370b57cec5SDimitry Andric // Add initializers for any closure decl refs. 44380b57cec5SDimitry Andric if (BlockDeclRefs.size()) { 44390b57cec5SDimitry Andric Expr *Exp; 44400b57cec5SDimitry Andric // Output all "by copy" declarations. 44410b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 44420b57cec5SDimitry Andric E = BlockByCopyDecls.end(); I != E; ++I) { 44430b57cec5SDimitry Andric if (isObjCType((*I)->getType())) { 44440b57cec5SDimitry Andric // FIXME: Conform to ABI ([[obj retain] autorelease]). 44450b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl((*I)->getName()); 44460b57cec5SDimitry Andric Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(), 44470b57cec5SDimitry Andric VK_LValue, SourceLocation()); 44480b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(*I)) { 44490b57cec5SDimitry Andric QualType QT = (*I)->getType(); 44500b57cec5SDimitry Andric QT = Context->getPointerType(QT); 4451fe6060f1SDimitry Andric Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp, 4452fe6060f1SDimitry Andric UO_AddrOf, QT, VK_PRValue, OK_Ordinary, 4453fe6060f1SDimitry Andric SourceLocation(), false, 4454fe6060f1SDimitry Andric FPOptionsOverride()); 44550b57cec5SDimitry Andric } 44560b57cec5SDimitry Andric } else if (isTopLevelBlockPointerType((*I)->getType())) { 44570b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl((*I)->getName()); 44580b57cec5SDimitry Andric Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(), 44590b57cec5SDimitry Andric VK_LValue, SourceLocation()); 44600b57cec5SDimitry Andric Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, 44610b57cec5SDimitry Andric Arg); 44620b57cec5SDimitry Andric } else { 44630b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl((*I)->getName()); 44640b57cec5SDimitry Andric Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(), 44650b57cec5SDimitry Andric VK_LValue, SourceLocation()); 44660b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(*I)) { 44670b57cec5SDimitry Andric QualType QT = (*I)->getType(); 44680b57cec5SDimitry Andric QT = Context->getPointerType(QT); 4469fe6060f1SDimitry Andric Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp, 4470fe6060f1SDimitry Andric UO_AddrOf, QT, VK_PRValue, OK_Ordinary, 4471fe6060f1SDimitry Andric SourceLocation(), false, 4472fe6060f1SDimitry Andric FPOptionsOverride()); 44730b57cec5SDimitry Andric } 44740b57cec5SDimitry Andric } 44750b57cec5SDimitry Andric InitExprs.push_back(Exp); 44760b57cec5SDimitry Andric } 44770b57cec5SDimitry Andric // Output all "by ref" declarations. 44780b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 44790b57cec5SDimitry Andric E = BlockByRefDecls.end(); I != E; ++I) { 44800b57cec5SDimitry Andric ValueDecl *ND = (*I); 44810b57cec5SDimitry Andric std::string Name(ND->getNameAsString()); 44820b57cec5SDimitry Andric std::string RecName; 44830b57cec5SDimitry Andric RewriteByRefString(RecName, Name, ND, true); 44840b57cec5SDimitry Andric IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 44850b57cec5SDimitry Andric + sizeof("struct")); 4486*5f757f3fSDimitry Andric RecordDecl *RD = 4487*5f757f3fSDimitry Andric RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 4488*5f757f3fSDimitry Andric SourceLocation(), SourceLocation(), II); 44890b57cec5SDimitry Andric assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); 44900b57cec5SDimitry Andric QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 44910b57cec5SDimitry Andric 44920b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl((*I)->getName()); 44930b57cec5SDimitry Andric Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(), 44940b57cec5SDimitry Andric VK_LValue, SourceLocation()); 44950b57cec5SDimitry Andric bool isNestedCapturedVar = false; 44960b57cec5SDimitry Andric if (block) 44970b57cec5SDimitry Andric for (const auto &CI : block->captures()) { 44980b57cec5SDimitry Andric const VarDecl *variable = CI.getVariable(); 44990b57cec5SDimitry Andric if (variable == ND && CI.isNested()) { 45000b57cec5SDimitry Andric assert (CI.isByRef() && 45010b57cec5SDimitry Andric "SynthBlockInitExpr - captured block variable is not byref"); 45020b57cec5SDimitry Andric isNestedCapturedVar = true; 45030b57cec5SDimitry Andric break; 45040b57cec5SDimitry Andric } 45050b57cec5SDimitry Andric } 45060b57cec5SDimitry Andric // captured nested byref variable has its address passed. Do not take 45070b57cec5SDimitry Andric // its address again. 45080b57cec5SDimitry Andric if (!isNestedCapturedVar) 45095ffd83dbSDimitry Andric Exp = UnaryOperator::Create( 45105ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, 4511fe6060f1SDimitry Andric Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary, 45125ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 45130b57cec5SDimitry Andric Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); 45140b57cec5SDimitry Andric InitExprs.push_back(Exp); 45150b57cec5SDimitry Andric } 45160b57cec5SDimitry Andric } 45170b57cec5SDimitry Andric if (ImportedBlockDecls.size()) { 45180b57cec5SDimitry Andric // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR 45190b57cec5SDimitry Andric int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR); 45200b57cec5SDimitry Andric unsigned IntSize = 45210b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 45220b57cec5SDimitry Andric Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 45230b57cec5SDimitry Andric Context->IntTy, SourceLocation()); 45240b57cec5SDimitry Andric InitExprs.push_back(FlagExp); 45250b57cec5SDimitry Andric } 45260b57cec5SDimitry Andric NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue, 4527e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 45285ffd83dbSDimitry Andric NewRep = UnaryOperator::Create( 45295ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf, 4530fe6060f1SDimitry Andric Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary, 45315ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 45320b57cec5SDimitry Andric NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, 45330b57cec5SDimitry Andric NewRep); 45340b57cec5SDimitry Andric BlockDeclRefs.clear(); 45350b57cec5SDimitry Andric BlockByRefDecls.clear(); 45360b57cec5SDimitry Andric BlockByRefDeclsPtrSet.clear(); 45370b57cec5SDimitry Andric BlockByCopyDecls.clear(); 45380b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.clear(); 45390b57cec5SDimitry Andric ImportedBlockDecls.clear(); 45400b57cec5SDimitry Andric return NewRep; 45410b57cec5SDimitry Andric } 45420b57cec5SDimitry Andric 45430b57cec5SDimitry Andric bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { 45440b57cec5SDimitry Andric if (const ObjCForCollectionStmt * CS = 45450b57cec5SDimitry Andric dyn_cast<ObjCForCollectionStmt>(Stmts.back())) 45460b57cec5SDimitry Andric return CS->getElement() == DS; 45470b57cec5SDimitry Andric return false; 45480b57cec5SDimitry Andric } 45490b57cec5SDimitry Andric 45500b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 45510b57cec5SDimitry Andric // Function Body / Expression rewriting 45520b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 45530b57cec5SDimitry Andric 45540b57cec5SDimitry Andric Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { 45550b57cec5SDimitry Andric if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 45560b57cec5SDimitry Andric isa<DoStmt>(S) || isa<ForStmt>(S)) 45570b57cec5SDimitry Andric Stmts.push_back(S); 45580b57cec5SDimitry Andric else if (isa<ObjCForCollectionStmt>(S)) { 45590b57cec5SDimitry Andric Stmts.push_back(S); 45600b57cec5SDimitry Andric ObjCBcLabelNo.push_back(++BcLabelCount); 45610b57cec5SDimitry Andric } 45620b57cec5SDimitry Andric 45630b57cec5SDimitry Andric // Pseudo-object operations and ivar references need special 45640b57cec5SDimitry Andric // treatment because we're going to recursively rewrite them. 45650b57cec5SDimitry Andric if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) { 45660b57cec5SDimitry Andric if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) { 45670b57cec5SDimitry Andric return RewritePropertyOrImplicitSetter(PseudoOp); 45680b57cec5SDimitry Andric } else { 45690b57cec5SDimitry Andric return RewritePropertyOrImplicitGetter(PseudoOp); 45700b57cec5SDimitry Andric } 45710b57cec5SDimitry Andric } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 45720b57cec5SDimitry Andric return RewriteObjCIvarRefExpr(IvarRefExpr); 45730b57cec5SDimitry Andric } 45740b57cec5SDimitry Andric 45750b57cec5SDimitry Andric SourceRange OrigStmtRange = S->getSourceRange(); 45760b57cec5SDimitry Andric 45770b57cec5SDimitry Andric // Perform a bottom up rewrite of all children. 45780b57cec5SDimitry Andric for (Stmt *&childStmt : S->children()) 45790b57cec5SDimitry Andric if (childStmt) { 45800b57cec5SDimitry Andric Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt); 45810b57cec5SDimitry Andric if (newStmt) { 45820b57cec5SDimitry Andric childStmt = newStmt; 45830b57cec5SDimitry Andric } 45840b57cec5SDimitry Andric } 45850b57cec5SDimitry Andric 45860b57cec5SDimitry Andric if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { 45870b57cec5SDimitry Andric SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs; 45880b57cec5SDimitry Andric llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; 45890b57cec5SDimitry Andric InnerContexts.insert(BE->getBlockDecl()); 45900b57cec5SDimitry Andric ImportedLocalExternalDecls.clear(); 45910b57cec5SDimitry Andric GetInnerBlockDeclRefExprs(BE->getBody(), 45920b57cec5SDimitry Andric InnerBlockDeclRefs, InnerContexts); 45930b57cec5SDimitry Andric // Rewrite the block body in place. 45940b57cec5SDimitry Andric Stmt *SaveCurrentBody = CurrentBody; 45950b57cec5SDimitry Andric CurrentBody = BE->getBody(); 45960b57cec5SDimitry Andric PropParentMap = nullptr; 45970b57cec5SDimitry Andric // block literal on rhs of a property-dot-sytax assignment 45980b57cec5SDimitry Andric // must be replaced by its synthesize ast so getRewrittenText 45990b57cec5SDimitry Andric // works as expected. In this case, what actually ends up on RHS 46000b57cec5SDimitry Andric // is the blockTranscribed which is the helper function for the 46010b57cec5SDimitry Andric // block literal; as in: self.c = ^() {[ace ARR];}; 46020b57cec5SDimitry Andric bool saveDisableReplaceStmt = DisableReplaceStmt; 46030b57cec5SDimitry Andric DisableReplaceStmt = false; 46040b57cec5SDimitry Andric RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); 46050b57cec5SDimitry Andric DisableReplaceStmt = saveDisableReplaceStmt; 46060b57cec5SDimitry Andric CurrentBody = SaveCurrentBody; 46070b57cec5SDimitry Andric PropParentMap = nullptr; 46080b57cec5SDimitry Andric ImportedLocalExternalDecls.clear(); 46090b57cec5SDimitry Andric // Now we snarf the rewritten text and stash it away for later use. 46100b57cec5SDimitry Andric std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); 46110b57cec5SDimitry Andric RewrittenBlockExprs[BE] = Str; 46120b57cec5SDimitry Andric 46130b57cec5SDimitry Andric Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); 46140b57cec5SDimitry Andric 46150b57cec5SDimitry Andric //blockTranscribed->dump(); 46160b57cec5SDimitry Andric ReplaceStmt(S, blockTranscribed); 46170b57cec5SDimitry Andric return blockTranscribed; 46180b57cec5SDimitry Andric } 46190b57cec5SDimitry Andric // Handle specific things. 46200b57cec5SDimitry Andric if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) 46210b57cec5SDimitry Andric return RewriteAtEncode(AtEncode); 46220b57cec5SDimitry Andric 46230b57cec5SDimitry Andric if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) 46240b57cec5SDimitry Andric return RewriteAtSelector(AtSelector); 46250b57cec5SDimitry Andric 46260b57cec5SDimitry Andric if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) 46270b57cec5SDimitry Andric return RewriteObjCStringLiteral(AtString); 46280b57cec5SDimitry Andric 46290b57cec5SDimitry Andric if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { 46300b57cec5SDimitry Andric #if 0 46310b57cec5SDimitry Andric // Before we rewrite it, put the original message expression in a comment. 46320b57cec5SDimitry Andric SourceLocation startLoc = MessExpr->getBeginLoc(); 46330b57cec5SDimitry Andric SourceLocation endLoc = MessExpr->getEndLoc(); 46340b57cec5SDimitry Andric 46350b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 46360b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(endLoc); 46370b57cec5SDimitry Andric 46380b57cec5SDimitry Andric std::string messString; 46390b57cec5SDimitry Andric messString += "// "; 46400b57cec5SDimitry Andric messString.append(startBuf, endBuf-startBuf+1); 46410b57cec5SDimitry Andric messString += "\n"; 46420b57cec5SDimitry Andric 46430b57cec5SDimitry Andric // FIXME: Missing definition of 46440b57cec5SDimitry Andric // InsertText(clang::SourceLocation, char const*, unsigned int). 46450b57cec5SDimitry Andric // InsertText(startLoc, messString); 46460b57cec5SDimitry Andric // Tried this, but it didn't work either... 46470b57cec5SDimitry Andric // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); 46480b57cec5SDimitry Andric #endif 46490b57cec5SDimitry Andric return RewriteMessageExpr(MessExpr); 46500b57cec5SDimitry Andric } 46510b57cec5SDimitry Andric 46520b57cec5SDimitry Andric if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) 46530b57cec5SDimitry Andric return RewriteObjCTryStmt(StmtTry); 46540b57cec5SDimitry Andric 46550b57cec5SDimitry Andric if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) 46560b57cec5SDimitry Andric return RewriteObjCSynchronizedStmt(StmtTry); 46570b57cec5SDimitry Andric 46580b57cec5SDimitry Andric if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) 46590b57cec5SDimitry Andric return RewriteObjCThrowStmt(StmtThrow); 46600b57cec5SDimitry Andric 46610b57cec5SDimitry Andric if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) 46620b57cec5SDimitry Andric return RewriteObjCProtocolExpr(ProtocolExp); 46630b57cec5SDimitry Andric 46640b57cec5SDimitry Andric if (ObjCForCollectionStmt *StmtForCollection = 46650b57cec5SDimitry Andric dyn_cast<ObjCForCollectionStmt>(S)) 46660b57cec5SDimitry Andric return RewriteObjCForCollectionStmt(StmtForCollection, 46670b57cec5SDimitry Andric OrigStmtRange.getEnd()); 46680b57cec5SDimitry Andric if (BreakStmt *StmtBreakStmt = 46690b57cec5SDimitry Andric dyn_cast<BreakStmt>(S)) 46700b57cec5SDimitry Andric return RewriteBreakStmt(StmtBreakStmt); 46710b57cec5SDimitry Andric if (ContinueStmt *StmtContinueStmt = 46720b57cec5SDimitry Andric dyn_cast<ContinueStmt>(S)) 46730b57cec5SDimitry Andric return RewriteContinueStmt(StmtContinueStmt); 46740b57cec5SDimitry Andric 46750b57cec5SDimitry Andric // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls 46760b57cec5SDimitry Andric // and cast exprs. 46770b57cec5SDimitry Andric if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 46780b57cec5SDimitry Andric // FIXME: What we're doing here is modifying the type-specifier that 46790b57cec5SDimitry Andric // precedes the first Decl. In the future the DeclGroup should have 46800b57cec5SDimitry Andric // a separate type-specifier that we can rewrite. 46810b57cec5SDimitry Andric // NOTE: We need to avoid rewriting the DeclStmt if it is within 46820b57cec5SDimitry Andric // the context of an ObjCForCollectionStmt. For example: 46830b57cec5SDimitry Andric // NSArray *someArray; 46840b57cec5SDimitry Andric // for (id <FooProtocol> index in someArray) ; 46850b57cec5SDimitry Andric // This is because RewriteObjCForCollectionStmt() does textual rewriting 46860b57cec5SDimitry Andric // and it depends on the original text locations/positions. 46870b57cec5SDimitry Andric if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS)) 46880b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); 46890b57cec5SDimitry Andric 46900b57cec5SDimitry Andric // Blocks rewrite rules. 46910b57cec5SDimitry Andric for (auto *SD : DS->decls()) { 46920b57cec5SDimitry Andric if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { 46930b57cec5SDimitry Andric if (isTopLevelBlockPointerType(ND->getType())) 46940b57cec5SDimitry Andric RewriteBlockPointerDecl(ND); 46950b57cec5SDimitry Andric else if (ND->getType()->isFunctionPointerType()) 46960b57cec5SDimitry Andric CheckFunctionPointerDecl(ND->getType(), ND); 46970b57cec5SDimitry Andric if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { 46980b57cec5SDimitry Andric if (VD->hasAttr<BlocksAttr>()) { 46990b57cec5SDimitry Andric static unsigned uniqueByrefDeclCount = 0; 47000b57cec5SDimitry Andric assert(!BlockByRefDeclNo.count(ND) && 47010b57cec5SDimitry Andric "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); 47020b57cec5SDimitry Andric BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; 47030b57cec5SDimitry Andric RewriteByRefVar(VD); 47040b57cec5SDimitry Andric } 47050b57cec5SDimitry Andric else 47060b57cec5SDimitry Andric RewriteTypeOfDecl(VD); 47070b57cec5SDimitry Andric } 47080b57cec5SDimitry Andric } 47090b57cec5SDimitry Andric if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { 47100b57cec5SDimitry Andric if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 47110b57cec5SDimitry Andric RewriteBlockPointerDecl(TD); 47120b57cec5SDimitry Andric else if (TD->getUnderlyingType()->isFunctionPointerType()) 47130b57cec5SDimitry Andric CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 47140b57cec5SDimitry Andric } 47150b57cec5SDimitry Andric } 47160b57cec5SDimitry Andric } 47170b57cec5SDimitry Andric 47180b57cec5SDimitry Andric if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) 47190b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(CE); 47200b57cec5SDimitry Andric 47210b57cec5SDimitry Andric if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 47220b57cec5SDimitry Andric isa<DoStmt>(S) || isa<ForStmt>(S)) { 47230b57cec5SDimitry Andric assert(!Stmts.empty() && "Statement stack is empty"); 47240b57cec5SDimitry Andric assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 47250b57cec5SDimitry Andric isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 47260b57cec5SDimitry Andric && "Statement stack mismatch"); 47270b57cec5SDimitry Andric Stmts.pop_back(); 47280b57cec5SDimitry Andric } 47290b57cec5SDimitry Andric // Handle blocks rewriting. 47300b57cec5SDimitry Andric if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 47310b57cec5SDimitry Andric ValueDecl *VD = DRE->getDecl(); 47320b57cec5SDimitry Andric if (VD->hasAttr<BlocksAttr>()) 47330b57cec5SDimitry Andric return RewriteBlockDeclRefExpr(DRE); 47340b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(VD)) 47350b57cec5SDimitry Andric return RewriteLocalVariableExternalStorage(DRE); 47360b57cec5SDimitry Andric } 47370b57cec5SDimitry Andric 47380b57cec5SDimitry Andric if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 47390b57cec5SDimitry Andric if (CE->getCallee()->getType()->isBlockPointerType()) { 47400b57cec5SDimitry Andric Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); 47410b57cec5SDimitry Andric ReplaceStmt(S, BlockCall); 47420b57cec5SDimitry Andric return BlockCall; 47430b57cec5SDimitry Andric } 47440b57cec5SDimitry Andric } 47450b57cec5SDimitry Andric if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) { 47460b57cec5SDimitry Andric RewriteCastExpr(CE); 47470b57cec5SDimitry Andric } 47480b57cec5SDimitry Andric #if 0 47490b57cec5SDimitry Andric if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 47500b57cec5SDimitry Andric CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), 47510b57cec5SDimitry Andric ICE->getSubExpr(), 47520b57cec5SDimitry Andric SourceLocation()); 47530b57cec5SDimitry Andric // Get the new text. 47540b57cec5SDimitry Andric std::string SStr; 47550b57cec5SDimitry Andric llvm::raw_string_ostream Buf(SStr); 47560b57cec5SDimitry Andric Replacement->printPretty(Buf); 47570b57cec5SDimitry Andric const std::string &Str = Buf.str(); 47580b57cec5SDimitry Andric 47590b57cec5SDimitry Andric printf("CAST = %s\n", &Str[0]); 47600b57cec5SDimitry Andric InsertText(ICE->getSubExpr()->getBeginLoc(), Str); 47610b57cec5SDimitry Andric delete S; 47620b57cec5SDimitry Andric return Replacement; 47630b57cec5SDimitry Andric } 47640b57cec5SDimitry Andric #endif 47650b57cec5SDimitry Andric // Return this stmt unmodified. 47660b57cec5SDimitry Andric return S; 47670b57cec5SDimitry Andric } 47680b57cec5SDimitry Andric 47690b57cec5SDimitry Andric void RewriteObjC::RewriteRecordBody(RecordDecl *RD) { 47700b57cec5SDimitry Andric for (auto *FD : RD->fields()) { 47710b57cec5SDimitry Andric if (isTopLevelBlockPointerType(FD->getType())) 47720b57cec5SDimitry Andric RewriteBlockPointerDecl(FD); 47730b57cec5SDimitry Andric if (FD->getType()->isObjCQualifiedIdType() || 47740b57cec5SDimitry Andric FD->getType()->isObjCQualifiedInterfaceType()) 47750b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(FD); 47760b57cec5SDimitry Andric } 47770b57cec5SDimitry Andric } 47780b57cec5SDimitry Andric 47790b57cec5SDimitry Andric /// HandleDeclInMainFile - This is called for each top-level decl defined in the 47800b57cec5SDimitry Andric /// main file of the input. 47810b57cec5SDimitry Andric void RewriteObjC::HandleDeclInMainFile(Decl *D) { 47820b57cec5SDimitry Andric switch (D->getKind()) { 47830b57cec5SDimitry Andric case Decl::Function: { 47840b57cec5SDimitry Andric FunctionDecl *FD = cast<FunctionDecl>(D); 47850b57cec5SDimitry Andric if (FD->isOverloadedOperator()) 47860b57cec5SDimitry Andric return; 47870b57cec5SDimitry Andric 47880b57cec5SDimitry Andric // Since function prototypes don't have ParmDecl's, we check the function 47890b57cec5SDimitry Andric // prototype. This enables us to rewrite function declarations and 47900b57cec5SDimitry Andric // definitions using the same code. 47910b57cec5SDimitry Andric RewriteBlocksInFunctionProtoType(FD->getType(), FD); 47920b57cec5SDimitry Andric 47930b57cec5SDimitry Andric if (!FD->isThisDeclarationADefinition()) 47940b57cec5SDimitry Andric break; 47950b57cec5SDimitry Andric 47960b57cec5SDimitry Andric // FIXME: If this should support Obj-C++, support CXXTryStmt 47970b57cec5SDimitry Andric if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { 47980b57cec5SDimitry Andric CurFunctionDef = FD; 47990b57cec5SDimitry Andric CurFunctionDeclToDeclareForBlock = FD; 48000b57cec5SDimitry Andric CurrentBody = Body; 48010b57cec5SDimitry Andric Body = 48020b57cec5SDimitry Andric cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 48030b57cec5SDimitry Andric FD->setBody(Body); 48040b57cec5SDimitry Andric CurrentBody = nullptr; 48050b57cec5SDimitry Andric if (PropParentMap) { 48060b57cec5SDimitry Andric delete PropParentMap; 48070b57cec5SDimitry Andric PropParentMap = nullptr; 48080b57cec5SDimitry Andric } 48090b57cec5SDimitry Andric // This synthesizes and inserts the block "impl" struct, invoke function, 48100b57cec5SDimitry Andric // and any copy/dispose helper functions. 48110b57cec5SDimitry Andric InsertBlockLiteralsWithinFunction(FD); 48120b57cec5SDimitry Andric CurFunctionDef = nullptr; 48130b57cec5SDimitry Andric CurFunctionDeclToDeclareForBlock = nullptr; 48140b57cec5SDimitry Andric } 48150b57cec5SDimitry Andric break; 48160b57cec5SDimitry Andric } 48170b57cec5SDimitry Andric case Decl::ObjCMethod: { 48180b57cec5SDimitry Andric ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); 48190b57cec5SDimitry Andric if (CompoundStmt *Body = MD->getCompoundBody()) { 48200b57cec5SDimitry Andric CurMethodDef = MD; 48210b57cec5SDimitry Andric CurrentBody = Body; 48220b57cec5SDimitry Andric Body = 48230b57cec5SDimitry Andric cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 48240b57cec5SDimitry Andric MD->setBody(Body); 48250b57cec5SDimitry Andric CurrentBody = nullptr; 48260b57cec5SDimitry Andric if (PropParentMap) { 48270b57cec5SDimitry Andric delete PropParentMap; 48280b57cec5SDimitry Andric PropParentMap = nullptr; 48290b57cec5SDimitry Andric } 48300b57cec5SDimitry Andric InsertBlockLiteralsWithinMethod(MD); 48310b57cec5SDimitry Andric CurMethodDef = nullptr; 48320b57cec5SDimitry Andric } 48330b57cec5SDimitry Andric break; 48340b57cec5SDimitry Andric } 48350b57cec5SDimitry Andric case Decl::ObjCImplementation: { 48360b57cec5SDimitry Andric ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D); 48370b57cec5SDimitry Andric ClassImplementation.push_back(CI); 48380b57cec5SDimitry Andric break; 48390b57cec5SDimitry Andric } 48400b57cec5SDimitry Andric case Decl::ObjCCategoryImpl: { 48410b57cec5SDimitry Andric ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D); 48420b57cec5SDimitry Andric CategoryImplementation.push_back(CI); 48430b57cec5SDimitry Andric break; 48440b57cec5SDimitry Andric } 48450b57cec5SDimitry Andric case Decl::Var: { 48460b57cec5SDimitry Andric VarDecl *VD = cast<VarDecl>(D); 48470b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(VD); 48480b57cec5SDimitry Andric if (isTopLevelBlockPointerType(VD->getType())) 48490b57cec5SDimitry Andric RewriteBlockPointerDecl(VD); 48500b57cec5SDimitry Andric else if (VD->getType()->isFunctionPointerType()) { 48510b57cec5SDimitry Andric CheckFunctionPointerDecl(VD->getType(), VD); 48520b57cec5SDimitry Andric if (VD->getInit()) { 48530b57cec5SDimitry Andric if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 48540b57cec5SDimitry Andric RewriteCastExpr(CE); 48550b57cec5SDimitry Andric } 48560b57cec5SDimitry Andric } 48570b57cec5SDimitry Andric } else if (VD->getType()->isRecordType()) { 4858a7dea167SDimitry Andric RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl(); 48590b57cec5SDimitry Andric if (RD->isCompleteDefinition()) 48600b57cec5SDimitry Andric RewriteRecordBody(RD); 48610b57cec5SDimitry Andric } 48620b57cec5SDimitry Andric if (VD->getInit()) { 48630b57cec5SDimitry Andric GlobalVarDecl = VD; 48640b57cec5SDimitry Andric CurrentBody = VD->getInit(); 48650b57cec5SDimitry Andric RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); 48660b57cec5SDimitry Andric CurrentBody = nullptr; 48670b57cec5SDimitry Andric if (PropParentMap) { 48680b57cec5SDimitry Andric delete PropParentMap; 48690b57cec5SDimitry Andric PropParentMap = nullptr; 48700b57cec5SDimitry Andric } 48710b57cec5SDimitry Andric SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName()); 48720b57cec5SDimitry Andric GlobalVarDecl = nullptr; 48730b57cec5SDimitry Andric 48740b57cec5SDimitry Andric // This is needed for blocks. 48750b57cec5SDimitry Andric if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 48760b57cec5SDimitry Andric RewriteCastExpr(CE); 48770b57cec5SDimitry Andric } 48780b57cec5SDimitry Andric } 48790b57cec5SDimitry Andric break; 48800b57cec5SDimitry Andric } 48810b57cec5SDimitry Andric case Decl::TypeAlias: 48820b57cec5SDimitry Andric case Decl::Typedef: { 48830b57cec5SDimitry Andric if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 48840b57cec5SDimitry Andric if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 48850b57cec5SDimitry Andric RewriteBlockPointerDecl(TD); 48860b57cec5SDimitry Andric else if (TD->getUnderlyingType()->isFunctionPointerType()) 48870b57cec5SDimitry Andric CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 48880b57cec5SDimitry Andric } 48890b57cec5SDimitry Andric break; 48900b57cec5SDimitry Andric } 48910b57cec5SDimitry Andric case Decl::CXXRecord: 48920b57cec5SDimitry Andric case Decl::Record: { 48930b57cec5SDimitry Andric RecordDecl *RD = cast<RecordDecl>(D); 48940b57cec5SDimitry Andric if (RD->isCompleteDefinition()) 48950b57cec5SDimitry Andric RewriteRecordBody(RD); 48960b57cec5SDimitry Andric break; 48970b57cec5SDimitry Andric } 48980b57cec5SDimitry Andric default: 48990b57cec5SDimitry Andric break; 49000b57cec5SDimitry Andric } 49010b57cec5SDimitry Andric // Nothing yet. 49020b57cec5SDimitry Andric } 49030b57cec5SDimitry Andric 49040b57cec5SDimitry Andric void RewriteObjC::HandleTranslationUnit(ASTContext &C) { 49050b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 49060b57cec5SDimitry Andric return; 49070b57cec5SDimitry Andric 49080b57cec5SDimitry Andric RewriteInclude(); 49090b57cec5SDimitry Andric 49100b57cec5SDimitry Andric // Here's a great place to add any extra declarations that may be needed. 49110b57cec5SDimitry Andric // Write out meta data for each @protocol(<expr>). 49120b57cec5SDimitry Andric for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) 49130b57cec5SDimitry Andric RewriteObjCProtocolMetaData(ProtDecl, "", "", Preamble); 49140b57cec5SDimitry Andric 49150b57cec5SDimitry Andric InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); 49160b57cec5SDimitry Andric if (ClassImplementation.size() || CategoryImplementation.size()) 49170b57cec5SDimitry Andric RewriteImplementations(); 49180b57cec5SDimitry Andric 49190b57cec5SDimitry Andric // Get the buffer corresponding to MainFileID. If we haven't changed it, then 49200b57cec5SDimitry Andric // we are done. 49210b57cec5SDimitry Andric if (const RewriteBuffer *RewriteBuf = 49220b57cec5SDimitry Andric Rewrite.getRewriteBufferFor(MainFileID)) { 49230b57cec5SDimitry Andric //printf("Changed:\n"); 49240b57cec5SDimitry Andric *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 49250b57cec5SDimitry Andric } else { 49260b57cec5SDimitry Andric llvm::errs() << "No changes\n"; 49270b57cec5SDimitry Andric } 49280b57cec5SDimitry Andric 49290b57cec5SDimitry Andric if (ClassImplementation.size() || CategoryImplementation.size() || 49300b57cec5SDimitry Andric ProtocolExprDecls.size()) { 49310b57cec5SDimitry Andric // Rewrite Objective-c meta data* 49320b57cec5SDimitry Andric std::string ResultStr; 49330b57cec5SDimitry Andric RewriteMetaDataIntoBuffer(ResultStr); 49340b57cec5SDimitry Andric // Emit metadata. 49350b57cec5SDimitry Andric *OutFile << ResultStr; 49360b57cec5SDimitry Andric } 49370b57cec5SDimitry Andric OutFile->flush(); 49380b57cec5SDimitry Andric } 49390b57cec5SDimitry Andric 49400b57cec5SDimitry Andric void RewriteObjCFragileABI::Initialize(ASTContext &context) { 49410b57cec5SDimitry Andric InitializeCommon(context); 49420b57cec5SDimitry Andric 49430b57cec5SDimitry Andric // declaring objc_selector outside the parameter list removes a silly 49440b57cec5SDimitry Andric // scope related warning... 49450b57cec5SDimitry Andric if (IsHeader) 49460b57cec5SDimitry Andric Preamble = "#pragma once\n"; 49470b57cec5SDimitry Andric Preamble += "struct objc_selector; struct objc_class;\n"; 49480b57cec5SDimitry Andric Preamble += "struct __rw_objc_super { struct objc_object *object; "; 49490b57cec5SDimitry Andric Preamble += "struct objc_object *superClass; "; 49500b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 49510b57cec5SDimitry Andric // Add a constructor for creating temporary objects. 49520b57cec5SDimitry Andric Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) " 49530b57cec5SDimitry Andric ": "; 49540b57cec5SDimitry Andric Preamble += "object(o), superClass(s) {} "; 49550b57cec5SDimitry Andric } 49560b57cec5SDimitry Andric Preamble += "};\n"; 49570b57cec5SDimitry Andric Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; 49580b57cec5SDimitry Andric Preamble += "typedef struct objc_object Protocol;\n"; 49590b57cec5SDimitry Andric Preamble += "#define _REWRITER_typedef_Protocol\n"; 49600b57cec5SDimitry Andric Preamble += "#endif\n"; 49610b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 49620b57cec5SDimitry Andric Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; 49630b57cec5SDimitry Andric Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; 49640b57cec5SDimitry Andric } else 49650b57cec5SDimitry Andric Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; 49660b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend"; 49670b57cec5SDimitry Andric Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 49680b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper"; 49690b57cec5SDimitry Andric Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 49700b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret"; 49710b57cec5SDimitry Andric Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 49720b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret"; 49730b57cec5SDimitry Andric Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 49740b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret"; 49750b57cec5SDimitry Andric Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 49760b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass"; 49770b57cec5SDimitry Andric Preamble += "(const char *);\n"; 49780b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; 49790b57cec5SDimitry Andric Preamble += "(struct objc_class *);\n"; 49800b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass"; 49810b57cec5SDimitry Andric Preamble += "(const char *);\n"; 49820b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n"; 49830b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n"; 49840b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n"; 49850b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n"; 49860b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match"; 49870b57cec5SDimitry Andric Preamble += "(struct objc_class *, struct objc_object *);\n"; 49880b57cec5SDimitry Andric // @synchronized hooks. 49890b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n"; 49900b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n"; 49910b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; 49920b57cec5SDimitry Andric Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; 49930b57cec5SDimitry Andric Preamble += "struct __objcFastEnumerationState {\n\t"; 49940b57cec5SDimitry Andric Preamble += "unsigned long state;\n\t"; 49950b57cec5SDimitry Andric Preamble += "void **itemsPtr;\n\t"; 49960b57cec5SDimitry Andric Preamble += "unsigned long *mutationsPtr;\n\t"; 49970b57cec5SDimitry Andric Preamble += "unsigned long extra[5];\n};\n"; 49980b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; 49990b57cec5SDimitry Andric Preamble += "#define __FASTENUMERATIONSTATE\n"; 50000b57cec5SDimitry Andric Preamble += "#endif\n"; 50010b57cec5SDimitry Andric Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; 50020b57cec5SDimitry Andric Preamble += "struct __NSConstantStringImpl {\n"; 50030b57cec5SDimitry Andric Preamble += " int *isa;\n"; 50040b57cec5SDimitry Andric Preamble += " int flags;\n"; 50050b57cec5SDimitry Andric Preamble += " char *str;\n"; 50060b57cec5SDimitry Andric Preamble += " long length;\n"; 50070b57cec5SDimitry Andric Preamble += "};\n"; 50080b57cec5SDimitry Andric Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; 50090b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; 50100b57cec5SDimitry Andric Preamble += "#else\n"; 50110b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; 50120b57cec5SDimitry Andric Preamble += "#endif\n"; 50130b57cec5SDimitry Andric Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; 50140b57cec5SDimitry Andric Preamble += "#endif\n"; 50150b57cec5SDimitry Andric // Blocks preamble. 50160b57cec5SDimitry Andric Preamble += "#ifndef BLOCK_IMPL\n"; 50170b57cec5SDimitry Andric Preamble += "#define BLOCK_IMPL\n"; 50180b57cec5SDimitry Andric Preamble += "struct __block_impl {\n"; 50190b57cec5SDimitry Andric Preamble += " void *isa;\n"; 50200b57cec5SDimitry Andric Preamble += " int Flags;\n"; 50210b57cec5SDimitry Andric Preamble += " int Reserved;\n"; 50220b57cec5SDimitry Andric Preamble += " void *FuncPtr;\n"; 50230b57cec5SDimitry Andric Preamble += "};\n"; 50240b57cec5SDimitry Andric Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; 50250b57cec5SDimitry Andric Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; 50260b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) " 50270b57cec5SDimitry Andric "void _Block_object_assign(void *, const void *, const int);\n"; 50280b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; 50290b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; 50300b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; 50310b57cec5SDimitry Andric Preamble += "#else\n"; 50320b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; 50330b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; 50340b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; 50350b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; 50360b57cec5SDimitry Andric Preamble += "#endif\n"; 50370b57cec5SDimitry Andric Preamble += "#endif\n"; 50380b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 50390b57cec5SDimitry Andric Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; 50400b57cec5SDimitry Andric Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; 50410b57cec5SDimitry Andric Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. 50420b57cec5SDimitry Andric Preamble += "#define __attribute__(X)\n"; 50430b57cec5SDimitry Andric Preamble += "#endif\n"; 50440b57cec5SDimitry Andric Preamble += "#define __weak\n"; 50450b57cec5SDimitry Andric } 50460b57cec5SDimitry Andric else { 50470b57cec5SDimitry Andric Preamble += "#define __block\n"; 50480b57cec5SDimitry Andric Preamble += "#define __weak\n"; 50490b57cec5SDimitry Andric } 50500b57cec5SDimitry Andric // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long 50510b57cec5SDimitry Andric // as this avoids warning in any 64bit/32bit compilation model. 50520b57cec5SDimitry Andric Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; 50530b57cec5SDimitry Andric } 50540b57cec5SDimitry Andric 50550b57cec5SDimitry Andric /// RewriteIvarOffsetComputation - This routine synthesizes computation of 50560b57cec5SDimitry Andric /// ivar offset. 50570b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 50580b57cec5SDimitry Andric std::string &Result) { 50590b57cec5SDimitry Andric if (ivar->isBitField()) { 50600b57cec5SDimitry Andric // FIXME: The hack below doesn't work for bitfields. For now, we simply 50610b57cec5SDimitry Andric // place all bitfields at offset 0. 50620b57cec5SDimitry Andric Result += "0"; 50630b57cec5SDimitry Andric } else { 50640b57cec5SDimitry Andric Result += "__OFFSETOFIVAR__(struct "; 50650b57cec5SDimitry Andric Result += ivar->getContainingInterface()->getNameAsString(); 50660b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 50670b57cec5SDimitry Andric Result += "_IMPL"; 50680b57cec5SDimitry Andric Result += ", "; 50690b57cec5SDimitry Andric Result += ivar->getNameAsString(); 50700b57cec5SDimitry Andric Result += ")"; 50710b57cec5SDimitry Andric } 50720b57cec5SDimitry Andric } 50730b57cec5SDimitry Andric 50740b57cec5SDimitry Andric /// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. 50750b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCProtocolMetaData( 50760b57cec5SDimitry Andric ObjCProtocolDecl *PDecl, StringRef prefix, 50770b57cec5SDimitry Andric StringRef ClassName, std::string &Result) { 50780b57cec5SDimitry Andric static bool objc_protocol_methods = false; 50790b57cec5SDimitry Andric 50800b57cec5SDimitry Andric // Output struct protocol_methods holder of method selector and type. 50810b57cec5SDimitry Andric if (!objc_protocol_methods && PDecl->hasDefinition()) { 50820b57cec5SDimitry Andric /* struct protocol_methods { 50830b57cec5SDimitry Andric SEL _cmd; 50840b57cec5SDimitry Andric char *method_types; 50850b57cec5SDimitry Andric } 50860b57cec5SDimitry Andric */ 50870b57cec5SDimitry Andric Result += "\nstruct _protocol_methods {\n"; 50880b57cec5SDimitry Andric Result += "\tstruct objc_selector *_cmd;\n"; 50890b57cec5SDimitry Andric Result += "\tchar *method_types;\n"; 50900b57cec5SDimitry Andric Result += "};\n"; 50910b57cec5SDimitry Andric 50920b57cec5SDimitry Andric objc_protocol_methods = true; 50930b57cec5SDimitry Andric } 50940b57cec5SDimitry Andric // Do not synthesize the protocol more than once. 50950b57cec5SDimitry Andric if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl())) 50960b57cec5SDimitry Andric return; 50970b57cec5SDimitry Andric 50980b57cec5SDimitry Andric if (ObjCProtocolDecl *Def = PDecl->getDefinition()) 50990b57cec5SDimitry Andric PDecl = Def; 51000b57cec5SDimitry Andric 51010b57cec5SDimitry Andric if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 51020b57cec5SDimitry Andric unsigned NumMethods = std::distance(PDecl->instmeth_begin(), 51030b57cec5SDimitry Andric PDecl->instmeth_end()); 51040b57cec5SDimitry Andric /* struct _objc_protocol_method_list { 51050b57cec5SDimitry Andric int protocol_method_count; 51060b57cec5SDimitry Andric struct protocol_methods protocols[]; 51070b57cec5SDimitry Andric } 51080b57cec5SDimitry Andric */ 51090b57cec5SDimitry Andric Result += "\nstatic struct {\n"; 51100b57cec5SDimitry Andric Result += "\tint protocol_method_count;\n"; 51110b57cec5SDimitry Andric Result += "\tstruct _protocol_methods protocol_methods["; 51120b57cec5SDimitry Andric Result += utostr(NumMethods); 51130b57cec5SDimitry Andric Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_"; 51140b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 51150b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 51160b57cec5SDimitry Andric "{\n\t" + utostr(NumMethods) + "\n"; 51170b57cec5SDimitry Andric 51180b57cec5SDimitry Andric // Output instance methods declared in this protocol. 51190b57cec5SDimitry Andric for (ObjCProtocolDecl::instmeth_iterator 51200b57cec5SDimitry Andric I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 51210b57cec5SDimitry Andric I != E; ++I) { 51220b57cec5SDimitry Andric if (I == PDecl->instmeth_begin()) 51230b57cec5SDimitry Andric Result += "\t ,{{(struct objc_selector *)\""; 51240b57cec5SDimitry Andric else 51250b57cec5SDimitry Andric Result += "\t ,{(struct objc_selector *)\""; 51260b57cec5SDimitry Andric Result += (*I)->getSelector().getAsString(); 51270b57cec5SDimitry Andric std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I); 51280b57cec5SDimitry Andric Result += "\", \""; 51290b57cec5SDimitry Andric Result += MethodTypeString; 51300b57cec5SDimitry Andric Result += "\"}\n"; 51310b57cec5SDimitry Andric } 51320b57cec5SDimitry Andric Result += "\t }\n};\n"; 51330b57cec5SDimitry Andric } 51340b57cec5SDimitry Andric 51350b57cec5SDimitry Andric // Output class methods declared in this protocol. 51360b57cec5SDimitry Andric unsigned NumMethods = std::distance(PDecl->classmeth_begin(), 51370b57cec5SDimitry Andric PDecl->classmeth_end()); 51380b57cec5SDimitry Andric if (NumMethods > 0) { 51390b57cec5SDimitry Andric /* struct _objc_protocol_method_list { 51400b57cec5SDimitry Andric int protocol_method_count; 51410b57cec5SDimitry Andric struct protocol_methods protocols[]; 51420b57cec5SDimitry Andric } 51430b57cec5SDimitry Andric */ 51440b57cec5SDimitry Andric Result += "\nstatic struct {\n"; 51450b57cec5SDimitry Andric Result += "\tint protocol_method_count;\n"; 51460b57cec5SDimitry Andric Result += "\tstruct _protocol_methods protocol_methods["; 51470b57cec5SDimitry Andric Result += utostr(NumMethods); 51480b57cec5SDimitry Andric Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_"; 51490b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 51500b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 51510b57cec5SDimitry Andric "{\n\t"; 51520b57cec5SDimitry Andric Result += utostr(NumMethods); 51530b57cec5SDimitry Andric Result += "\n"; 51540b57cec5SDimitry Andric 51550b57cec5SDimitry Andric // Output instance methods declared in this protocol. 51560b57cec5SDimitry Andric for (ObjCProtocolDecl::classmeth_iterator 51570b57cec5SDimitry Andric I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 51580b57cec5SDimitry Andric I != E; ++I) { 51590b57cec5SDimitry Andric if (I == PDecl->classmeth_begin()) 51600b57cec5SDimitry Andric Result += "\t ,{{(struct objc_selector *)\""; 51610b57cec5SDimitry Andric else 51620b57cec5SDimitry Andric Result += "\t ,{(struct objc_selector *)\""; 51630b57cec5SDimitry Andric Result += (*I)->getSelector().getAsString(); 51640b57cec5SDimitry Andric std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I); 51650b57cec5SDimitry Andric Result += "\", \""; 51660b57cec5SDimitry Andric Result += MethodTypeString; 51670b57cec5SDimitry Andric Result += "\"}\n"; 51680b57cec5SDimitry Andric } 51690b57cec5SDimitry Andric Result += "\t }\n};\n"; 51700b57cec5SDimitry Andric } 51710b57cec5SDimitry Andric 51720b57cec5SDimitry Andric // Output: 51730b57cec5SDimitry Andric /* struct _objc_protocol { 51740b57cec5SDimitry Andric // Objective-C 1.0 extensions 51750b57cec5SDimitry Andric struct _objc_protocol_extension *isa; 51760b57cec5SDimitry Andric char *protocol_name; 51770b57cec5SDimitry Andric struct _objc_protocol **protocol_list; 51780b57cec5SDimitry Andric struct _objc_protocol_method_list *instance_methods; 51790b57cec5SDimitry Andric struct _objc_protocol_method_list *class_methods; 51800b57cec5SDimitry Andric }; 51810b57cec5SDimitry Andric */ 51820b57cec5SDimitry Andric static bool objc_protocol = false; 51830b57cec5SDimitry Andric if (!objc_protocol) { 51840b57cec5SDimitry Andric Result += "\nstruct _objc_protocol {\n"; 51850b57cec5SDimitry Andric Result += "\tstruct _objc_protocol_extension *isa;\n"; 51860b57cec5SDimitry Andric Result += "\tchar *protocol_name;\n"; 51870b57cec5SDimitry Andric Result += "\tstruct _objc_protocol **protocol_list;\n"; 51880b57cec5SDimitry Andric Result += "\tstruct _objc_protocol_method_list *instance_methods;\n"; 51890b57cec5SDimitry Andric Result += "\tstruct _objc_protocol_method_list *class_methods;\n"; 51900b57cec5SDimitry Andric Result += "};\n"; 51910b57cec5SDimitry Andric 51920b57cec5SDimitry Andric objc_protocol = true; 51930b57cec5SDimitry Andric } 51940b57cec5SDimitry Andric 51950b57cec5SDimitry Andric Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_"; 51960b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 51970b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 51980b57cec5SDimitry Andric "{\n\t0, \""; 51990b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 52000b57cec5SDimitry Andric Result += "\", 0, "; 52010b57cec5SDimitry Andric if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 52020b57cec5SDimitry Andric Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; 52030b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 52040b57cec5SDimitry Andric Result += ", "; 52050b57cec5SDimitry Andric } 52060b57cec5SDimitry Andric else 52070b57cec5SDimitry Andric Result += "0, "; 52080b57cec5SDimitry Andric if (PDecl->classmeth_begin() != PDecl->classmeth_end()) { 52090b57cec5SDimitry Andric Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; 52100b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 52110b57cec5SDimitry Andric Result += "\n"; 52120b57cec5SDimitry Andric } 52130b57cec5SDimitry Andric else 52140b57cec5SDimitry Andric Result += "0\n"; 52150b57cec5SDimitry Andric Result += "};\n"; 52160b57cec5SDimitry Andric 52170b57cec5SDimitry Andric // Mark this protocol as having been generated. 52180b57cec5SDimitry Andric if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second) 52190b57cec5SDimitry Andric llvm_unreachable("protocol already synthesized"); 52200b57cec5SDimitry Andric } 52210b57cec5SDimitry Andric 52220b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData( 52230b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &Protocols, 52240b57cec5SDimitry Andric StringRef prefix, StringRef ClassName, 52250b57cec5SDimitry Andric std::string &Result) { 52260b57cec5SDimitry Andric if (Protocols.empty()) return; 52270b57cec5SDimitry Andric 52280b57cec5SDimitry Andric for (unsigned i = 0; i != Protocols.size(); i++) 52290b57cec5SDimitry Andric RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result); 52300b57cec5SDimitry Andric 52310b57cec5SDimitry Andric // Output the top lovel protocol meta-data for the class. 52320b57cec5SDimitry Andric /* struct _objc_protocol_list { 52330b57cec5SDimitry Andric struct _objc_protocol_list *next; 52340b57cec5SDimitry Andric int protocol_count; 52350b57cec5SDimitry Andric struct _objc_protocol *class_protocols[]; 52360b57cec5SDimitry Andric } 52370b57cec5SDimitry Andric */ 52380b57cec5SDimitry Andric Result += "\nstatic struct {\n"; 52390b57cec5SDimitry Andric Result += "\tstruct _objc_protocol_list *next;\n"; 52400b57cec5SDimitry Andric Result += "\tint protocol_count;\n"; 52410b57cec5SDimitry Andric Result += "\tstruct _objc_protocol *class_protocols["; 52420b57cec5SDimitry Andric Result += utostr(Protocols.size()); 52430b57cec5SDimitry Andric Result += "];\n} _OBJC_"; 52440b57cec5SDimitry Andric Result += prefix; 52450b57cec5SDimitry Andric Result += "_PROTOCOLS_"; 52460b57cec5SDimitry Andric Result += ClassName; 52470b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 52480b57cec5SDimitry Andric "{\n\t0, "; 52490b57cec5SDimitry Andric Result += utostr(Protocols.size()); 52500b57cec5SDimitry Andric Result += "\n"; 52510b57cec5SDimitry Andric 52520b57cec5SDimitry Andric Result += "\t,{&_OBJC_PROTOCOL_"; 52530b57cec5SDimitry Andric Result += Protocols[0]->getNameAsString(); 52540b57cec5SDimitry Andric Result += " \n"; 52550b57cec5SDimitry Andric 52560b57cec5SDimitry Andric for (unsigned i = 1; i != Protocols.size(); i++) { 52570b57cec5SDimitry Andric Result += "\t ,&_OBJC_PROTOCOL_"; 52580b57cec5SDimitry Andric Result += Protocols[i]->getNameAsString(); 52590b57cec5SDimitry Andric Result += "\n"; 52600b57cec5SDimitry Andric } 52610b57cec5SDimitry Andric Result += "\t }\n};\n"; 52620b57cec5SDimitry Andric } 52630b57cec5SDimitry Andric 52640b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 52650b57cec5SDimitry Andric std::string &Result) { 52660b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 52670b57cec5SDimitry Andric 52680b57cec5SDimitry Andric // Explicitly declared @interface's are already synthesized. 52690b57cec5SDimitry Andric if (CDecl->isImplicitInterfaceDecl()) { 52700b57cec5SDimitry Andric // FIXME: Implementation of a class with no @interface (legacy) does not 52710b57cec5SDimitry Andric // produce correct synthesis as yet. 52720b57cec5SDimitry Andric RewriteObjCInternalStruct(CDecl, Result); 52730b57cec5SDimitry Andric } 52740b57cec5SDimitry Andric 52750b57cec5SDimitry Andric // Build _objc_ivar_list metadata for classes ivars if needed 5276e8d8bef9SDimitry Andric unsigned NumIvars = 5277e8d8bef9SDimitry Andric !IDecl->ivar_empty() ? IDecl->ivar_size() : CDecl->ivar_size(); 52780b57cec5SDimitry Andric if (NumIvars > 0) { 52790b57cec5SDimitry Andric static bool objc_ivar = false; 52800b57cec5SDimitry Andric if (!objc_ivar) { 52810b57cec5SDimitry Andric /* struct _objc_ivar { 52820b57cec5SDimitry Andric char *ivar_name; 52830b57cec5SDimitry Andric char *ivar_type; 52840b57cec5SDimitry Andric int ivar_offset; 52850b57cec5SDimitry Andric }; 52860b57cec5SDimitry Andric */ 52870b57cec5SDimitry Andric Result += "\nstruct _objc_ivar {\n"; 52880b57cec5SDimitry Andric Result += "\tchar *ivar_name;\n"; 52890b57cec5SDimitry Andric Result += "\tchar *ivar_type;\n"; 52900b57cec5SDimitry Andric Result += "\tint ivar_offset;\n"; 52910b57cec5SDimitry Andric Result += "};\n"; 52920b57cec5SDimitry Andric 52930b57cec5SDimitry Andric objc_ivar = true; 52940b57cec5SDimitry Andric } 52950b57cec5SDimitry Andric 52960b57cec5SDimitry Andric /* struct { 52970b57cec5SDimitry Andric int ivar_count; 52980b57cec5SDimitry Andric struct _objc_ivar ivar_list[nIvars]; 52990b57cec5SDimitry Andric }; 53000b57cec5SDimitry Andric */ 53010b57cec5SDimitry Andric Result += "\nstatic struct {\n"; 53020b57cec5SDimitry Andric Result += "\tint ivar_count;\n"; 53030b57cec5SDimitry Andric Result += "\tstruct _objc_ivar ivar_list["; 53040b57cec5SDimitry Andric Result += utostr(NumIvars); 53050b57cec5SDimitry Andric Result += "];\n} _OBJC_INSTANCE_VARIABLES_"; 53060b57cec5SDimitry Andric Result += IDecl->getNameAsString(); 53070b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 53080b57cec5SDimitry Andric "{\n\t"; 53090b57cec5SDimitry Andric Result += utostr(NumIvars); 53100b57cec5SDimitry Andric Result += "\n"; 53110b57cec5SDimitry Andric 53120b57cec5SDimitry Andric ObjCInterfaceDecl::ivar_iterator IVI, IVE; 53130b57cec5SDimitry Andric SmallVector<ObjCIvarDecl *, 8> IVars; 53140b57cec5SDimitry Andric if (!IDecl->ivar_empty()) { 53150b57cec5SDimitry Andric for (auto *IV : IDecl->ivars()) 53160b57cec5SDimitry Andric IVars.push_back(IV); 53170b57cec5SDimitry Andric IVI = IDecl->ivar_begin(); 53180b57cec5SDimitry Andric IVE = IDecl->ivar_end(); 53190b57cec5SDimitry Andric } else { 53200b57cec5SDimitry Andric IVI = CDecl->ivar_begin(); 53210b57cec5SDimitry Andric IVE = CDecl->ivar_end(); 53220b57cec5SDimitry Andric } 53230b57cec5SDimitry Andric Result += "\t,{{\""; 53240b57cec5SDimitry Andric Result += IVI->getNameAsString(); 53250b57cec5SDimitry Andric Result += "\", \""; 53260b57cec5SDimitry Andric std::string TmpString, StrEncoding; 53270b57cec5SDimitry Andric Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI); 53280b57cec5SDimitry Andric QuoteDoublequotes(TmpString, StrEncoding); 53290b57cec5SDimitry Andric Result += StrEncoding; 53300b57cec5SDimitry Andric Result += "\", "; 53310b57cec5SDimitry Andric RewriteIvarOffsetComputation(*IVI, Result); 53320b57cec5SDimitry Andric Result += "}\n"; 53330b57cec5SDimitry Andric for (++IVI; IVI != IVE; ++IVI) { 53340b57cec5SDimitry Andric Result += "\t ,{\""; 53350b57cec5SDimitry Andric Result += IVI->getNameAsString(); 53360b57cec5SDimitry Andric Result += "\", \""; 53370b57cec5SDimitry Andric std::string TmpString, StrEncoding; 53380b57cec5SDimitry Andric Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI); 53390b57cec5SDimitry Andric QuoteDoublequotes(TmpString, StrEncoding); 53400b57cec5SDimitry Andric Result += StrEncoding; 53410b57cec5SDimitry Andric Result += "\", "; 53420b57cec5SDimitry Andric RewriteIvarOffsetComputation(*IVI, Result); 53430b57cec5SDimitry Andric Result += "}\n"; 53440b57cec5SDimitry Andric } 53450b57cec5SDimitry Andric 53460b57cec5SDimitry Andric Result += "\t }\n};\n"; 53470b57cec5SDimitry Andric } 53480b57cec5SDimitry Andric 53490b57cec5SDimitry Andric // Build _objc_method_list for class's instance methods if needed 53500b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods()); 53510b57cec5SDimitry Andric 53520b57cec5SDimitry Andric // If any of our property implementations have associated getters or 53530b57cec5SDimitry Andric // setters, produce metadata for them as well. 53540b57cec5SDimitry Andric for (const auto *Prop : IDecl->property_impls()) { 53550b57cec5SDimitry Andric if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 53560b57cec5SDimitry Andric continue; 53570b57cec5SDimitry Andric if (!Prop->getPropertyIvarDecl()) 53580b57cec5SDimitry Andric continue; 53590b57cec5SDimitry Andric ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 53600b57cec5SDimitry Andric if (!PD) 53610b57cec5SDimitry Andric continue; 5362480093f4SDimitry Andric if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl()) 53630b57cec5SDimitry Andric if (!Getter->isDefined()) 53640b57cec5SDimitry Andric InstanceMethods.push_back(Getter); 53650b57cec5SDimitry Andric if (PD->isReadOnly()) 53660b57cec5SDimitry Andric continue; 5367480093f4SDimitry Andric if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl()) 53680b57cec5SDimitry Andric if (!Setter->isDefined()) 53690b57cec5SDimitry Andric InstanceMethods.push_back(Setter); 53700b57cec5SDimitry Andric } 53710b57cec5SDimitry Andric RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 53720b57cec5SDimitry Andric true, "", IDecl->getName(), Result); 53730b57cec5SDimitry Andric 53740b57cec5SDimitry Andric // Build _objc_method_list for class's class methods if needed 53750b57cec5SDimitry Andric RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 53760b57cec5SDimitry Andric false, "", IDecl->getName(), Result); 53770b57cec5SDimitry Andric 53780b57cec5SDimitry Andric // Protocols referenced in class declaration? 53790b57cec5SDimitry Andric RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), 53800b57cec5SDimitry Andric "CLASS", CDecl->getName(), Result); 53810b57cec5SDimitry Andric 53820b57cec5SDimitry Andric // Declaration of class/meta-class metadata 53830b57cec5SDimitry Andric /* struct _objc_class { 53840b57cec5SDimitry Andric struct _objc_class *isa; // or const char *root_class_name when metadata 53850b57cec5SDimitry Andric const char *super_class_name; 53860b57cec5SDimitry Andric char *name; 53870b57cec5SDimitry Andric long version; 53880b57cec5SDimitry Andric long info; 53890b57cec5SDimitry Andric long instance_size; 53900b57cec5SDimitry Andric struct _objc_ivar_list *ivars; 53910b57cec5SDimitry Andric struct _objc_method_list *methods; 53920b57cec5SDimitry Andric struct objc_cache *cache; 53930b57cec5SDimitry Andric struct objc_protocol_list *protocols; 53940b57cec5SDimitry Andric const char *ivar_layout; 53950b57cec5SDimitry Andric struct _objc_class_ext *ext; 53960b57cec5SDimitry Andric }; 53970b57cec5SDimitry Andric */ 53980b57cec5SDimitry Andric static bool objc_class = false; 53990b57cec5SDimitry Andric if (!objc_class) { 54000b57cec5SDimitry Andric Result += "\nstruct _objc_class {\n"; 54010b57cec5SDimitry Andric Result += "\tstruct _objc_class *isa;\n"; 54020b57cec5SDimitry Andric Result += "\tconst char *super_class_name;\n"; 54030b57cec5SDimitry Andric Result += "\tchar *name;\n"; 54040b57cec5SDimitry Andric Result += "\tlong version;\n"; 54050b57cec5SDimitry Andric Result += "\tlong info;\n"; 54060b57cec5SDimitry Andric Result += "\tlong instance_size;\n"; 54070b57cec5SDimitry Andric Result += "\tstruct _objc_ivar_list *ivars;\n"; 54080b57cec5SDimitry Andric Result += "\tstruct _objc_method_list *methods;\n"; 54090b57cec5SDimitry Andric Result += "\tstruct objc_cache *cache;\n"; 54100b57cec5SDimitry Andric Result += "\tstruct _objc_protocol_list *protocols;\n"; 54110b57cec5SDimitry Andric Result += "\tconst char *ivar_layout;\n"; 54120b57cec5SDimitry Andric Result += "\tstruct _objc_class_ext *ext;\n"; 54130b57cec5SDimitry Andric Result += "};\n"; 54140b57cec5SDimitry Andric objc_class = true; 54150b57cec5SDimitry Andric } 54160b57cec5SDimitry Andric 54170b57cec5SDimitry Andric // Meta-class metadata generation. 54180b57cec5SDimitry Andric ObjCInterfaceDecl *RootClass = nullptr; 54190b57cec5SDimitry Andric ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); 54200b57cec5SDimitry Andric while (SuperClass) { 54210b57cec5SDimitry Andric RootClass = SuperClass; 54220b57cec5SDimitry Andric SuperClass = SuperClass->getSuperClass(); 54230b57cec5SDimitry Andric } 54240b57cec5SDimitry Andric SuperClass = CDecl->getSuperClass(); 54250b57cec5SDimitry Andric 54260b57cec5SDimitry Andric Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; 54270b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54280b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 54290b57cec5SDimitry Andric "{\n\t(struct _objc_class *)\""; 54300b57cec5SDimitry Andric Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString()); 54310b57cec5SDimitry Andric Result += "\""; 54320b57cec5SDimitry Andric 54330b57cec5SDimitry Andric if (SuperClass) { 54340b57cec5SDimitry Andric Result += ", \""; 54350b57cec5SDimitry Andric Result += SuperClass->getNameAsString(); 54360b57cec5SDimitry Andric Result += "\", \""; 54370b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54380b57cec5SDimitry Andric Result += "\""; 54390b57cec5SDimitry Andric } 54400b57cec5SDimitry Andric else { 54410b57cec5SDimitry Andric Result += ", 0, \""; 54420b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54430b57cec5SDimitry Andric Result += "\""; 54440b57cec5SDimitry Andric } 54450b57cec5SDimitry Andric // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. 54460b57cec5SDimitry Andric // 'info' field is initialized to CLS_META(2) for metaclass 54470b57cec5SDimitry Andric Result += ", 0,2, sizeof(struct _objc_class), 0"; 54480b57cec5SDimitry Andric if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 54490b57cec5SDimitry Andric Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; 54500b57cec5SDimitry Andric Result += IDecl->getNameAsString(); 54510b57cec5SDimitry Andric Result += "\n"; 54520b57cec5SDimitry Andric } 54530b57cec5SDimitry Andric else 54540b57cec5SDimitry Andric Result += ", 0\n"; 54550b57cec5SDimitry Andric if (CDecl->protocol_begin() != CDecl->protocol_end()) { 54560b57cec5SDimitry Andric Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; 54570b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54580b57cec5SDimitry Andric Result += ",0,0\n"; 54590b57cec5SDimitry Andric } 54600b57cec5SDimitry Andric else 54610b57cec5SDimitry Andric Result += "\t,0,0,0,0\n"; 54620b57cec5SDimitry Andric Result += "};\n"; 54630b57cec5SDimitry Andric 54640b57cec5SDimitry Andric // class metadata generation. 54650b57cec5SDimitry Andric Result += "\nstatic struct _objc_class _OBJC_CLASS_"; 54660b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54670b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= " 54680b57cec5SDimitry Andric "{\n\t&_OBJC_METACLASS_"; 54690b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54700b57cec5SDimitry Andric if (SuperClass) { 54710b57cec5SDimitry Andric Result += ", \""; 54720b57cec5SDimitry Andric Result += SuperClass->getNameAsString(); 54730b57cec5SDimitry Andric Result += "\", \""; 54740b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54750b57cec5SDimitry Andric Result += "\""; 54760b57cec5SDimitry Andric } 54770b57cec5SDimitry Andric else { 54780b57cec5SDimitry Andric Result += ", 0, \""; 54790b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54800b57cec5SDimitry Andric Result += "\""; 54810b57cec5SDimitry Andric } 54820b57cec5SDimitry Andric // 'info' field is initialized to CLS_CLASS(1) for class 54830b57cec5SDimitry Andric Result += ", 0,1"; 54840b57cec5SDimitry Andric if (!ObjCSynthesizedStructs.count(CDecl)) 54850b57cec5SDimitry Andric Result += ",0"; 54860b57cec5SDimitry Andric else { 54870b57cec5SDimitry Andric // class has size. Must synthesize its size. 54880b57cec5SDimitry Andric Result += ",sizeof(struct "; 54890b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54900b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 54910b57cec5SDimitry Andric Result += "_IMPL"; 54920b57cec5SDimitry Andric Result += ")"; 54930b57cec5SDimitry Andric } 54940b57cec5SDimitry Andric if (NumIvars > 0) { 54950b57cec5SDimitry Andric Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_"; 54960b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 54970b57cec5SDimitry Andric Result += "\n\t"; 54980b57cec5SDimitry Andric } 54990b57cec5SDimitry Andric else 55000b57cec5SDimitry Andric Result += ",0"; 55010b57cec5SDimitry Andric if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 55020b57cec5SDimitry Andric Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; 55030b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 55040b57cec5SDimitry Andric Result += ", 0\n\t"; 55050b57cec5SDimitry Andric } 55060b57cec5SDimitry Andric else 55070b57cec5SDimitry Andric Result += ",0,0"; 55080b57cec5SDimitry Andric if (CDecl->protocol_begin() != CDecl->protocol_end()) { 55090b57cec5SDimitry Andric Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; 55100b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 55110b57cec5SDimitry Andric Result += ", 0,0\n"; 55120b57cec5SDimitry Andric } 55130b57cec5SDimitry Andric else 55140b57cec5SDimitry Andric Result += ",0,0,0\n"; 55150b57cec5SDimitry Andric Result += "};\n"; 55160b57cec5SDimitry Andric } 55170b57cec5SDimitry Andric 55180b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) { 55190b57cec5SDimitry Andric int ClsDefCount = ClassImplementation.size(); 55200b57cec5SDimitry Andric int CatDefCount = CategoryImplementation.size(); 55210b57cec5SDimitry Andric 55220b57cec5SDimitry Andric // For each implemented class, write out all its meta data. 55230b57cec5SDimitry Andric for (int i = 0; i < ClsDefCount; i++) 55240b57cec5SDimitry Andric RewriteObjCClassMetaData(ClassImplementation[i], Result); 55250b57cec5SDimitry Andric 55260b57cec5SDimitry Andric // For each implemented category, write out all its meta data. 55270b57cec5SDimitry Andric for (int i = 0; i < CatDefCount; i++) 55280b57cec5SDimitry Andric RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); 55290b57cec5SDimitry Andric 55300b57cec5SDimitry Andric // Write objc_symtab metadata 55310b57cec5SDimitry Andric /* 55320b57cec5SDimitry Andric struct _objc_symtab 55330b57cec5SDimitry Andric { 55340b57cec5SDimitry Andric long sel_ref_cnt; 55350b57cec5SDimitry Andric SEL *refs; 55360b57cec5SDimitry Andric short cls_def_cnt; 55370b57cec5SDimitry Andric short cat_def_cnt; 55380b57cec5SDimitry Andric void *defs[cls_def_cnt + cat_def_cnt]; 55390b57cec5SDimitry Andric }; 55400b57cec5SDimitry Andric */ 55410b57cec5SDimitry Andric 55420b57cec5SDimitry Andric Result += "\nstruct _objc_symtab {\n"; 55430b57cec5SDimitry Andric Result += "\tlong sel_ref_cnt;\n"; 55440b57cec5SDimitry Andric Result += "\tSEL *refs;\n"; 55450b57cec5SDimitry Andric Result += "\tshort cls_def_cnt;\n"; 55460b57cec5SDimitry Andric Result += "\tshort cat_def_cnt;\n"; 55470b57cec5SDimitry Andric Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n"; 55480b57cec5SDimitry Andric Result += "};\n\n"; 55490b57cec5SDimitry Andric 55500b57cec5SDimitry Andric Result += "static struct _objc_symtab " 55510b57cec5SDimitry Andric "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n"; 55520b57cec5SDimitry Andric Result += "\t0, 0, " + utostr(ClsDefCount) 55530b57cec5SDimitry Andric + ", " + utostr(CatDefCount) + "\n"; 55540b57cec5SDimitry Andric for (int i = 0; i < ClsDefCount; i++) { 55550b57cec5SDimitry Andric Result += "\t,&_OBJC_CLASS_"; 55560b57cec5SDimitry Andric Result += ClassImplementation[i]->getNameAsString(); 55570b57cec5SDimitry Andric Result += "\n"; 55580b57cec5SDimitry Andric } 55590b57cec5SDimitry Andric 55600b57cec5SDimitry Andric for (int i = 0; i < CatDefCount; i++) { 55610b57cec5SDimitry Andric Result += "\t,&_OBJC_CATEGORY_"; 55620b57cec5SDimitry Andric Result += CategoryImplementation[i]->getClassInterface()->getNameAsString(); 55630b57cec5SDimitry Andric Result += "_"; 55640b57cec5SDimitry Andric Result += CategoryImplementation[i]->getNameAsString(); 55650b57cec5SDimitry Andric Result += "\n"; 55660b57cec5SDimitry Andric } 55670b57cec5SDimitry Andric 55680b57cec5SDimitry Andric Result += "};\n\n"; 55690b57cec5SDimitry Andric 55700b57cec5SDimitry Andric // Write objc_module metadata 55710b57cec5SDimitry Andric 55720b57cec5SDimitry Andric /* 55730b57cec5SDimitry Andric struct _objc_module { 55740b57cec5SDimitry Andric long version; 55750b57cec5SDimitry Andric long size; 55760b57cec5SDimitry Andric const char *name; 55770b57cec5SDimitry Andric struct _objc_symtab *symtab; 55780b57cec5SDimitry Andric } 55790b57cec5SDimitry Andric */ 55800b57cec5SDimitry Andric 55810b57cec5SDimitry Andric Result += "\nstruct _objc_module {\n"; 55820b57cec5SDimitry Andric Result += "\tlong version;\n"; 55830b57cec5SDimitry Andric Result += "\tlong size;\n"; 55840b57cec5SDimitry Andric Result += "\tconst char *name;\n"; 55850b57cec5SDimitry Andric Result += "\tstruct _objc_symtab *symtab;\n"; 55860b57cec5SDimitry Andric Result += "};\n\n"; 55870b57cec5SDimitry Andric Result += "static struct _objc_module " 55880b57cec5SDimitry Andric "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n"; 55890b57cec5SDimitry Andric Result += "\t" + utostr(OBJC_ABI_VERSION) + 55900b57cec5SDimitry Andric ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n"; 55910b57cec5SDimitry Andric Result += "};\n\n"; 55920b57cec5SDimitry Andric 55930b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 55940b57cec5SDimitry Andric if (ProtocolExprDecls.size()) { 55950b57cec5SDimitry Andric Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n"; 55960b57cec5SDimitry Andric Result += "#pragma data_seg(push, \".objc_protocol$B\")\n"; 55970b57cec5SDimitry Andric for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) { 55980b57cec5SDimitry Andric Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_"; 55990b57cec5SDimitry Andric Result += ProtDecl->getNameAsString(); 56000b57cec5SDimitry Andric Result += " = &_OBJC_PROTOCOL_"; 56010b57cec5SDimitry Andric Result += ProtDecl->getNameAsString(); 56020b57cec5SDimitry Andric Result += ";\n"; 56030b57cec5SDimitry Andric } 56040b57cec5SDimitry Andric Result += "#pragma data_seg(pop)\n\n"; 56050b57cec5SDimitry Andric } 56060b57cec5SDimitry Andric Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n"; 56070b57cec5SDimitry Andric Result += "#pragma data_seg(push, \".objc_module_info$B\")\n"; 56080b57cec5SDimitry Andric Result += "static struct _objc_module *_POINTER_OBJC_MODULES = "; 56090b57cec5SDimitry Andric Result += "&_OBJC_MODULES;\n"; 56100b57cec5SDimitry Andric Result += "#pragma data_seg(pop)\n\n"; 56110b57cec5SDimitry Andric } 56120b57cec5SDimitry Andric } 56130b57cec5SDimitry Andric 56140b57cec5SDimitry Andric /// RewriteObjCCategoryImplDecl - Rewrite metadata for each category 56150b57cec5SDimitry Andric /// implementation. 56160b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, 56170b57cec5SDimitry Andric std::string &Result) { 56180b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 56190b57cec5SDimitry Andric // Find category declaration for this implementation. 56200b57cec5SDimitry Andric ObjCCategoryDecl *CDecl 56210b57cec5SDimitry Andric = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier()); 56220b57cec5SDimitry Andric 56230b57cec5SDimitry Andric std::string FullCategoryName = ClassDecl->getNameAsString(); 56240b57cec5SDimitry Andric FullCategoryName += '_'; 56250b57cec5SDimitry Andric FullCategoryName += IDecl->getNameAsString(); 56260b57cec5SDimitry Andric 56270b57cec5SDimitry Andric // Build _objc_method_list for class's instance methods if needed 56280b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods()); 56290b57cec5SDimitry Andric 56300b57cec5SDimitry Andric // If any of our property implementations have associated getters or 56310b57cec5SDimitry Andric // setters, produce metadata for them as well. 56320b57cec5SDimitry Andric for (const auto *Prop : IDecl->property_impls()) { 56330b57cec5SDimitry Andric if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 56340b57cec5SDimitry Andric continue; 56350b57cec5SDimitry Andric if (!Prop->getPropertyIvarDecl()) 56360b57cec5SDimitry Andric continue; 56370b57cec5SDimitry Andric ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 56380b57cec5SDimitry Andric if (!PD) 56390b57cec5SDimitry Andric continue; 5640480093f4SDimitry Andric if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl()) 56410b57cec5SDimitry Andric InstanceMethods.push_back(Getter); 56420b57cec5SDimitry Andric if (PD->isReadOnly()) 56430b57cec5SDimitry Andric continue; 5644480093f4SDimitry Andric if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl()) 56450b57cec5SDimitry Andric InstanceMethods.push_back(Setter); 56460b57cec5SDimitry Andric } 56470b57cec5SDimitry Andric RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 56480b57cec5SDimitry Andric true, "CATEGORY_", FullCategoryName, Result); 56490b57cec5SDimitry Andric 56500b57cec5SDimitry Andric // Build _objc_method_list for class's class methods if needed 56510b57cec5SDimitry Andric RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 56520b57cec5SDimitry Andric false, "CATEGORY_", FullCategoryName, Result); 56530b57cec5SDimitry Andric 56540b57cec5SDimitry Andric // Protocols referenced in class declaration? 56550b57cec5SDimitry Andric // Null CDecl is case of a category implementation with no category interface 56560b57cec5SDimitry Andric if (CDecl) 56570b57cec5SDimitry Andric RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", 56580b57cec5SDimitry Andric FullCategoryName, Result); 56590b57cec5SDimitry Andric /* struct _objc_category { 56600b57cec5SDimitry Andric char *category_name; 56610b57cec5SDimitry Andric char *class_name; 56620b57cec5SDimitry Andric struct _objc_method_list *instance_methods; 56630b57cec5SDimitry Andric struct _objc_method_list *class_methods; 56640b57cec5SDimitry Andric struct _objc_protocol_list *protocols; 56650b57cec5SDimitry Andric // Objective-C 1.0 extensions 56660b57cec5SDimitry Andric uint32_t size; // sizeof (struct _objc_category) 56670b57cec5SDimitry Andric struct _objc_property_list *instance_properties; // category's own 56680b57cec5SDimitry Andric // @property decl. 56690b57cec5SDimitry Andric }; 56700b57cec5SDimitry Andric */ 56710b57cec5SDimitry Andric 56720b57cec5SDimitry Andric static bool objc_category = false; 56730b57cec5SDimitry Andric if (!objc_category) { 56740b57cec5SDimitry Andric Result += "\nstruct _objc_category {\n"; 56750b57cec5SDimitry Andric Result += "\tchar *category_name;\n"; 56760b57cec5SDimitry Andric Result += "\tchar *class_name;\n"; 56770b57cec5SDimitry Andric Result += "\tstruct _objc_method_list *instance_methods;\n"; 56780b57cec5SDimitry Andric Result += "\tstruct _objc_method_list *class_methods;\n"; 56790b57cec5SDimitry Andric Result += "\tstruct _objc_protocol_list *protocols;\n"; 56800b57cec5SDimitry Andric Result += "\tunsigned int size;\n"; 56810b57cec5SDimitry Andric Result += "\tstruct _objc_property_list *instance_properties;\n"; 56820b57cec5SDimitry Andric Result += "};\n"; 56830b57cec5SDimitry Andric objc_category = true; 56840b57cec5SDimitry Andric } 56850b57cec5SDimitry Andric Result += "\nstatic struct _objc_category _OBJC_CATEGORY_"; 56860b57cec5SDimitry Andric Result += FullCategoryName; 56870b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\""; 56880b57cec5SDimitry Andric Result += IDecl->getNameAsString(); 56890b57cec5SDimitry Andric Result += "\"\n\t, \""; 56900b57cec5SDimitry Andric Result += ClassDecl->getNameAsString(); 56910b57cec5SDimitry Andric Result += "\"\n"; 56920b57cec5SDimitry Andric 56930b57cec5SDimitry Andric if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 56940b57cec5SDimitry Andric Result += "\t, (struct _objc_method_list *)" 56950b57cec5SDimitry Andric "&_OBJC_CATEGORY_INSTANCE_METHODS_"; 56960b57cec5SDimitry Andric Result += FullCategoryName; 56970b57cec5SDimitry Andric Result += "\n"; 56980b57cec5SDimitry Andric } 56990b57cec5SDimitry Andric else 57000b57cec5SDimitry Andric Result += "\t, 0\n"; 57010b57cec5SDimitry Andric if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 57020b57cec5SDimitry Andric Result += "\t, (struct _objc_method_list *)" 57030b57cec5SDimitry Andric "&_OBJC_CATEGORY_CLASS_METHODS_"; 57040b57cec5SDimitry Andric Result += FullCategoryName; 57050b57cec5SDimitry Andric Result += "\n"; 57060b57cec5SDimitry Andric } 57070b57cec5SDimitry Andric else 57080b57cec5SDimitry Andric Result += "\t, 0\n"; 57090b57cec5SDimitry Andric 57100b57cec5SDimitry Andric if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) { 57110b57cec5SDimitry Andric Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; 57120b57cec5SDimitry Andric Result += FullCategoryName; 57130b57cec5SDimitry Andric Result += "\n"; 57140b57cec5SDimitry Andric } 57150b57cec5SDimitry Andric else 57160b57cec5SDimitry Andric Result += "\t, 0\n"; 57170b57cec5SDimitry Andric Result += "\t, sizeof(struct _objc_category), 0\n};\n"; 57180b57cec5SDimitry Andric } 57190b57cec5SDimitry Andric 57200b57cec5SDimitry Andric // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or 57210b57cec5SDimitry Andric /// class methods. 57220b57cec5SDimitry Andric template<typename MethodIterator> 57230b57cec5SDimitry Andric void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 57240b57cec5SDimitry Andric MethodIterator MethodEnd, 57250b57cec5SDimitry Andric bool IsInstanceMethod, 57260b57cec5SDimitry Andric StringRef prefix, 57270b57cec5SDimitry Andric StringRef ClassName, 57280b57cec5SDimitry Andric std::string &Result) { 57290b57cec5SDimitry Andric if (MethodBegin == MethodEnd) return; 57300b57cec5SDimitry Andric 57310b57cec5SDimitry Andric if (!objc_impl_method) { 57320b57cec5SDimitry Andric /* struct _objc_method { 57330b57cec5SDimitry Andric SEL _cmd; 57340b57cec5SDimitry Andric char *method_types; 57350b57cec5SDimitry Andric void *_imp; 57360b57cec5SDimitry Andric } 57370b57cec5SDimitry Andric */ 57380b57cec5SDimitry Andric Result += "\nstruct _objc_method {\n"; 57390b57cec5SDimitry Andric Result += "\tSEL _cmd;\n"; 57400b57cec5SDimitry Andric Result += "\tchar *method_types;\n"; 57410b57cec5SDimitry Andric Result += "\tvoid *_imp;\n"; 57420b57cec5SDimitry Andric Result += "};\n"; 57430b57cec5SDimitry Andric 57440b57cec5SDimitry Andric objc_impl_method = true; 57450b57cec5SDimitry Andric } 57460b57cec5SDimitry Andric 57470b57cec5SDimitry Andric // Build _objc_method_list for class's methods if needed 57480b57cec5SDimitry Andric 57490b57cec5SDimitry Andric /* struct { 57500b57cec5SDimitry Andric struct _objc_method_list *next_method; 57510b57cec5SDimitry Andric int method_count; 57520b57cec5SDimitry Andric struct _objc_method method_list[]; 57530b57cec5SDimitry Andric } 57540b57cec5SDimitry Andric */ 57550b57cec5SDimitry Andric unsigned NumMethods = std::distance(MethodBegin, MethodEnd); 57560b57cec5SDimitry Andric Result += "\nstatic struct {\n"; 57570b57cec5SDimitry Andric Result += "\tstruct _objc_method_list *next_method;\n"; 57580b57cec5SDimitry Andric Result += "\tint method_count;\n"; 57590b57cec5SDimitry Andric Result += "\tstruct _objc_method method_list["; 57600b57cec5SDimitry Andric Result += utostr(NumMethods); 57610b57cec5SDimitry Andric Result += "];\n} _OBJC_"; 57620b57cec5SDimitry Andric Result += prefix; 57630b57cec5SDimitry Andric Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; 57640b57cec5SDimitry Andric Result += "_METHODS_"; 57650b57cec5SDimitry Andric Result += ClassName; 57660b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __"; 57670b57cec5SDimitry Andric Result += IsInstanceMethod ? "inst" : "cls"; 57680b57cec5SDimitry Andric Result += "_meth\")))= "; 57690b57cec5SDimitry Andric Result += "{\n\t0, " + utostr(NumMethods) + "\n"; 57700b57cec5SDimitry Andric 57710b57cec5SDimitry Andric Result += "\t,{{(SEL)\""; 57720b57cec5SDimitry Andric Result += (*MethodBegin)->getSelector().getAsString(); 57730b57cec5SDimitry Andric std::string MethodTypeString = 57740b57cec5SDimitry Andric Context->getObjCEncodingForMethodDecl(*MethodBegin); 57750b57cec5SDimitry Andric Result += "\", \""; 57760b57cec5SDimitry Andric Result += MethodTypeString; 57770b57cec5SDimitry Andric Result += "\", (void *)"; 57780b57cec5SDimitry Andric Result += MethodInternalNames[*MethodBegin]; 57790b57cec5SDimitry Andric Result += "}\n"; 57800b57cec5SDimitry Andric for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { 57810b57cec5SDimitry Andric Result += "\t ,{(SEL)\""; 57820b57cec5SDimitry Andric Result += (*MethodBegin)->getSelector().getAsString(); 57830b57cec5SDimitry Andric std::string MethodTypeString = 57840b57cec5SDimitry Andric Context->getObjCEncodingForMethodDecl(*MethodBegin); 57850b57cec5SDimitry Andric Result += "\", \""; 57860b57cec5SDimitry Andric Result += MethodTypeString; 57870b57cec5SDimitry Andric Result += "\", (void *)"; 57880b57cec5SDimitry Andric Result += MethodInternalNames[*MethodBegin]; 57890b57cec5SDimitry Andric Result += "}\n"; 57900b57cec5SDimitry Andric } 57910b57cec5SDimitry Andric Result += "\t }\n};\n"; 57920b57cec5SDimitry Andric } 57930b57cec5SDimitry Andric 57940b57cec5SDimitry Andric Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { 57950b57cec5SDimitry Andric SourceRange OldRange = IV->getSourceRange(); 57960b57cec5SDimitry Andric Expr *BaseExpr = IV->getBase(); 57970b57cec5SDimitry Andric 57980b57cec5SDimitry Andric // Rewrite the base, but without actually doing replaces. 57990b57cec5SDimitry Andric { 58000b57cec5SDimitry Andric DisableReplaceStmtScope S(*this); 58010b57cec5SDimitry Andric BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr)); 58020b57cec5SDimitry Andric IV->setBase(BaseExpr); 58030b57cec5SDimitry Andric } 58040b57cec5SDimitry Andric 58050b57cec5SDimitry Andric ObjCIvarDecl *D = IV->getDecl(); 58060b57cec5SDimitry Andric 58070b57cec5SDimitry Andric Expr *Replacement = IV; 58080b57cec5SDimitry Andric if (CurMethodDef) { 58090b57cec5SDimitry Andric if (BaseExpr->getType()->isObjCObjectPointerType()) { 58100b57cec5SDimitry Andric const ObjCInterfaceType *iFaceDecl = 58110b57cec5SDimitry Andric dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 58120b57cec5SDimitry Andric assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); 58130b57cec5SDimitry Andric // lookup which class implements the instance variable. 58140b57cec5SDimitry Andric ObjCInterfaceDecl *clsDeclared = nullptr; 58150b57cec5SDimitry Andric iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 58160b57cec5SDimitry Andric clsDeclared); 58170b57cec5SDimitry Andric assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 58180b57cec5SDimitry Andric 58190b57cec5SDimitry Andric // Synthesize an explicit cast to gain access to the ivar. 58205ffd83dbSDimitry Andric std::string RecName = 58215ffd83dbSDimitry Andric std::string(clsDeclared->getIdentifier()->getName()); 58220b57cec5SDimitry Andric RecName += "_IMPL"; 58230b57cec5SDimitry Andric IdentifierInfo *II = &Context->Idents.get(RecName); 5824*5f757f3fSDimitry Andric RecordDecl *RD = 5825*5f757f3fSDimitry Andric RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 5826*5f757f3fSDimitry Andric SourceLocation(), SourceLocation(), II); 58270b57cec5SDimitry Andric assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 58280b57cec5SDimitry Andric QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 58290b57cec5SDimitry Andric CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 58300b57cec5SDimitry Andric CK_BitCast, 58310b57cec5SDimitry Andric IV->getBase()); 58320b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 58330b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(), 58340b57cec5SDimitry Andric OldRange.getEnd(), 58350b57cec5SDimitry Andric castExpr); 58360b57cec5SDimitry Andric if (IV->isFreeIvar() && 58370b57cec5SDimitry Andric declaresSameEntity(CurMethodDef->getClassInterface(), 58380b57cec5SDimitry Andric iFaceDecl->getDecl())) { 58390b57cec5SDimitry Andric MemberExpr *ME = MemberExpr::CreateImplicit( 58400b57cec5SDimitry Andric *Context, PE, true, D, D->getType(), VK_LValue, OK_Ordinary); 58410b57cec5SDimitry Andric Replacement = ME; 58420b57cec5SDimitry Andric } else { 58430b57cec5SDimitry Andric IV->setBase(PE); 58440b57cec5SDimitry Andric } 58450b57cec5SDimitry Andric } 58460b57cec5SDimitry Andric } else { // we are outside a method. 58470b57cec5SDimitry Andric assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); 58480b57cec5SDimitry Andric 58490b57cec5SDimitry Andric // Explicit ivar refs need to have a cast inserted. 58500b57cec5SDimitry Andric // FIXME: consider sharing some of this code with the code above. 58510b57cec5SDimitry Andric if (BaseExpr->getType()->isObjCObjectPointerType()) { 58520b57cec5SDimitry Andric const ObjCInterfaceType *iFaceDecl = 58530b57cec5SDimitry Andric dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 58540b57cec5SDimitry Andric // lookup which class implements the instance variable. 58550b57cec5SDimitry Andric ObjCInterfaceDecl *clsDeclared = nullptr; 58560b57cec5SDimitry Andric iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 58570b57cec5SDimitry Andric clsDeclared); 58580b57cec5SDimitry Andric assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 58590b57cec5SDimitry Andric 58600b57cec5SDimitry Andric // Synthesize an explicit cast to gain access to the ivar. 58615ffd83dbSDimitry Andric std::string RecName = 58625ffd83dbSDimitry Andric std::string(clsDeclared->getIdentifier()->getName()); 58630b57cec5SDimitry Andric RecName += "_IMPL"; 58640b57cec5SDimitry Andric IdentifierInfo *II = &Context->Idents.get(RecName); 5865*5f757f3fSDimitry Andric RecordDecl *RD = 5866*5f757f3fSDimitry Andric RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 5867*5f757f3fSDimitry Andric SourceLocation(), SourceLocation(), II); 58680b57cec5SDimitry Andric assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 58690b57cec5SDimitry Andric QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 58700b57cec5SDimitry Andric CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 58710b57cec5SDimitry Andric CK_BitCast, 58720b57cec5SDimitry Andric IV->getBase()); 58730b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 58740b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr( 58750b57cec5SDimitry Andric IV->getBase()->getBeginLoc(), IV->getBase()->getEndLoc(), castExpr); 58760b57cec5SDimitry Andric // Cannot delete IV->getBase(), since PE points to it. 58770b57cec5SDimitry Andric // Replace the old base with the cast. This is important when doing 58780b57cec5SDimitry Andric // embedded rewrites. For example, [newInv->_container addObject:0]. 58790b57cec5SDimitry Andric IV->setBase(PE); 58800b57cec5SDimitry Andric } 58810b57cec5SDimitry Andric } 58820b57cec5SDimitry Andric 58830b57cec5SDimitry Andric ReplaceStmtWithRange(IV, Replacement, OldRange); 58840b57cec5SDimitry Andric return Replacement; 58850b57cec5SDimitry Andric } 58860b57cec5SDimitry Andric 58870b57cec5SDimitry Andric #endif // CLANG_ENABLE_OBJC_REWRITER 5888