10b57cec5SDimitry Andric //===-- RewriteModernObjC.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/Basic/TargetInfo.h" 230b57cec5SDimitry Andric #include "clang/Config/config.h" 240b57cec5SDimitry Andric #include "clang/Lex/Lexer.h" 250b57cec5SDimitry Andric #include "clang/Rewrite/Core/Rewriter.h" 260b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 2781ad6265SDimitry Andric #include "llvm/ADT/SetVector.h" 280b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 290b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 300b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 310b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 320b57cec5SDimitry Andric #include <memory> 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric #if CLANG_ENABLE_OBJC_REWRITER 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric using namespace clang; 370b57cec5SDimitry Andric using llvm::utostr; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric namespace { 400b57cec5SDimitry Andric class RewriteModernObjC : public ASTConsumer { 410b57cec5SDimitry Andric protected: 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric enum { 440b57cec5SDimitry Andric BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 450b57cec5SDimitry Andric block, ... */ 460b57cec5SDimitry Andric BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 470b57cec5SDimitry Andric BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the 480b57cec5SDimitry Andric __block variable */ 490b57cec5SDimitry Andric BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 500b57cec5SDimitry Andric helpers */ 510b57cec5SDimitry Andric BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 520b57cec5SDimitry Andric support routines */ 530b57cec5SDimitry Andric BLOCK_BYREF_CURRENT_MAX = 256 540b57cec5SDimitry Andric }; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric enum { 570b57cec5SDimitry Andric BLOCK_NEEDS_FREE = (1 << 24), 580b57cec5SDimitry Andric BLOCK_HAS_COPY_DISPOSE = (1 << 25), 590b57cec5SDimitry Andric BLOCK_HAS_CXX_OBJ = (1 << 26), 600b57cec5SDimitry Andric BLOCK_IS_GC = (1 << 27), 610b57cec5SDimitry Andric BLOCK_IS_GLOBAL = (1 << 28), 620b57cec5SDimitry Andric BLOCK_HAS_DESCRIPTOR = (1 << 29) 630b57cec5SDimitry Andric }; 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric Rewriter Rewrite; 660b57cec5SDimitry Andric DiagnosticsEngine &Diags; 670b57cec5SDimitry Andric const LangOptions &LangOpts; 680b57cec5SDimitry Andric ASTContext *Context; 690b57cec5SDimitry Andric SourceManager *SM; 700b57cec5SDimitry Andric TranslationUnitDecl *TUDecl; 710b57cec5SDimitry Andric FileID MainFileID; 720b57cec5SDimitry Andric const char *MainFileStart, *MainFileEnd; 730b57cec5SDimitry Andric Stmt *CurrentBody; 740b57cec5SDimitry Andric ParentMap *PropParentMap; // created lazily. 750b57cec5SDimitry Andric std::string InFileName; 760b57cec5SDimitry Andric std::unique_ptr<raw_ostream> OutFile; 770b57cec5SDimitry Andric std::string Preamble; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric TypeDecl *ProtocolTypeDecl; 800b57cec5SDimitry Andric VarDecl *GlobalVarDecl; 810b57cec5SDimitry Andric Expr *GlobalConstructionExp; 820b57cec5SDimitry Andric unsigned RewriteFailedDiag; 830b57cec5SDimitry Andric unsigned GlobalBlockRewriteFailedDiag; 840b57cec5SDimitry Andric // ObjC string constant support. 850b57cec5SDimitry Andric unsigned NumObjCStringLiterals; 860b57cec5SDimitry Andric VarDecl *ConstantStringClassReference; 870b57cec5SDimitry Andric RecordDecl *NSStringRecord; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric // ObjC foreach break/continue generation support. 900b57cec5SDimitry Andric int BcLabelCount; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric unsigned TryFinallyContainsReturnDiag; 930b57cec5SDimitry Andric // Needed for super. 940b57cec5SDimitry Andric ObjCMethodDecl *CurMethodDef; 950b57cec5SDimitry Andric RecordDecl *SuperStructDecl; 960b57cec5SDimitry Andric RecordDecl *ConstantStringDecl; 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric FunctionDecl *MsgSendFunctionDecl; 990b57cec5SDimitry Andric FunctionDecl *MsgSendSuperFunctionDecl; 1000b57cec5SDimitry Andric FunctionDecl *MsgSendStretFunctionDecl; 1010b57cec5SDimitry Andric FunctionDecl *MsgSendSuperStretFunctionDecl; 1020b57cec5SDimitry Andric FunctionDecl *MsgSendFpretFunctionDecl; 1030b57cec5SDimitry Andric FunctionDecl *GetClassFunctionDecl; 1040b57cec5SDimitry Andric FunctionDecl *GetMetaClassFunctionDecl; 1050b57cec5SDimitry Andric FunctionDecl *GetSuperClassFunctionDecl; 1060b57cec5SDimitry Andric FunctionDecl *SelGetUidFunctionDecl; 1070b57cec5SDimitry Andric FunctionDecl *CFStringFunctionDecl; 1080b57cec5SDimitry Andric FunctionDecl *SuperConstructorFunctionDecl; 1090b57cec5SDimitry Andric FunctionDecl *CurFunctionDef; 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric /* Misc. containers needed for meta-data rewrite. */ 1120b57cec5SDimitry Andric SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; 1130b57cec5SDimitry Andric SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; 1140b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; 1150b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; 1160b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces; 1170b57cec5SDimitry Andric llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags; 1180b57cec5SDimitry Andric SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen; 1190b57cec5SDimitry Andric /// DefinedNonLazyClasses - List of defined "non-lazy" classes. 1200b57cec5SDimitry Andric SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /// DefinedNonLazyCategories - List of defined "non-lazy" categories. 1230b57cec5SDimitry Andric SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric SmallVector<Stmt *, 32> Stmts; 1260b57cec5SDimitry Andric SmallVector<int, 8> ObjCBcLabelNo; 1270b57cec5SDimitry Andric // Remember all the @protocol(<expr>) expressions. 1280b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric llvm::DenseSet<uint64_t> CopyDestroyCache; 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric // Block expressions. 1330b57cec5SDimitry Andric SmallVector<BlockExpr *, 32> Blocks; 1340b57cec5SDimitry Andric SmallVector<int, 32> InnerDeclRefsCount; 1350b57cec5SDimitry Andric SmallVector<DeclRefExpr *, 32> InnerDeclRefs; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric SmallVector<DeclRefExpr *, 32> BlockDeclRefs; 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric // Block related declarations. 1400b57cec5SDimitry Andric SmallVector<ValueDecl *, 8> BlockByCopyDecls; 1410b57cec5SDimitry Andric llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; 1420b57cec5SDimitry Andric SmallVector<ValueDecl *, 8> BlockByRefDecls; 1430b57cec5SDimitry Andric llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; 1440b57cec5SDimitry Andric llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; 1450b57cec5SDimitry Andric llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; 1460b57cec5SDimitry Andric llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls; 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; 1490b57cec5SDimitry Andric llvm::DenseMap<ObjCInterfaceDecl *, 1500b57cec5SDimitry Andric llvm::SmallSetVector<ObjCIvarDecl *, 8> > ReferencedIvars; 1510b57cec5SDimitry Andric 1520b57cec5SDimitry Andric // ivar bitfield grouping containers 1530b57cec5SDimitry Andric llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups; 1540b57cec5SDimitry Andric llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber; 1550b57cec5SDimitry Andric // This container maps an <class, group number for ivar> tuple to the type 1560b57cec5SDimitry Andric // of the struct where the bitfield belongs. 1570b57cec5SDimitry Andric llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType; 1580b57cec5SDimitry Andric SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen; 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // This maps an original source AST to it's rewritten form. This allows 1610b57cec5SDimitry Andric // us to avoid rewriting the same node twice (which is very uncommon). 1620b57cec5SDimitry Andric // This is needed to support some of the exotic property rewriting. 1630b57cec5SDimitry Andric llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // Needed for header files being rewritten 1660b57cec5SDimitry Andric bool IsHeader; 1670b57cec5SDimitry Andric bool SilenceRewriteMacroWarning; 1680b57cec5SDimitry Andric bool GenerateLineInfo; 1690b57cec5SDimitry Andric bool objc_impl_method; 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric bool DisableReplaceStmt; 1720b57cec5SDimitry Andric class DisableReplaceStmtScope { 1730b57cec5SDimitry Andric RewriteModernObjC &R; 1740b57cec5SDimitry Andric bool SavedValue; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric public: 1770b57cec5SDimitry Andric DisableReplaceStmtScope(RewriteModernObjC &R) 1780b57cec5SDimitry Andric : R(R), SavedValue(R.DisableReplaceStmt) { 1790b57cec5SDimitry Andric R.DisableReplaceStmt = true; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric ~DisableReplaceStmtScope() { 1820b57cec5SDimitry Andric R.DisableReplaceStmt = SavedValue; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric }; 1850b57cec5SDimitry Andric void InitializeCommon(ASTContext &context); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric public: 1880b57cec5SDimitry Andric llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric // Top Level Driver code. 1910b57cec5SDimitry Andric bool HandleTopLevelDecl(DeclGroupRef D) override { 1920b57cec5SDimitry Andric for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 1930b57cec5SDimitry Andric if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) { 1940b57cec5SDimitry Andric if (!Class->isThisDeclarationADefinition()) { 1950b57cec5SDimitry Andric RewriteForwardClassDecl(D); 1960b57cec5SDimitry Andric break; 1970b57cec5SDimitry Andric } else { 1980b57cec5SDimitry Andric // Keep track of all interface declarations seen. 1990b57cec5SDimitry Andric ObjCInterfacesSeen.push_back(Class); 2000b57cec5SDimitry Andric break; 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) { 2050b57cec5SDimitry Andric if (!Proto->isThisDeclarationADefinition()) { 2060b57cec5SDimitry Andric RewriteForwardProtocolDecl(D); 2070b57cec5SDimitry Andric break; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I)) { 2120b57cec5SDimitry Andric // Under modern abi, we cannot translate body of the function 2130b57cec5SDimitry Andric // yet until all class extensions and its implementation is seen. 2140b57cec5SDimitry Andric // This is because they may introduce new bitfields which must go 2150b57cec5SDimitry Andric // into their grouping struct. 2160b57cec5SDimitry Andric if (FDecl->isThisDeclarationADefinition() && 2170b57cec5SDimitry Andric // Not c functions defined inside an objc container. 2180b57cec5SDimitry Andric !FDecl->isTopLevelDeclInObjCContainer()) { 2190b57cec5SDimitry Andric FunctionDefinitionsSeen.push_back(FDecl); 2200b57cec5SDimitry Andric break; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric HandleTopLevelSingleDecl(*I); 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric return true; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { 2290b57cec5SDimitry Andric for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 2300b57cec5SDimitry Andric if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(*I)) { 2310b57cec5SDimitry Andric if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 2320b57cec5SDimitry Andric RewriteBlockPointerDecl(TD); 2330b57cec5SDimitry Andric else if (TD->getUnderlyingType()->isFunctionPointerType()) 2340b57cec5SDimitry Andric CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 2350b57cec5SDimitry Andric else 2360b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(TD); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric } 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric void HandleTopLevelSingleDecl(Decl *D); 2420b57cec5SDimitry Andric void HandleDeclInMainFile(Decl *D); 2430b57cec5SDimitry Andric RewriteModernObjC(std::string inFile, std::unique_ptr<raw_ostream> OS, 2440b57cec5SDimitry Andric DiagnosticsEngine &D, const LangOptions &LOpts, 2450b57cec5SDimitry Andric bool silenceMacroWarn, bool LineInfo); 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric ~RewriteModernObjC() override {} 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric void HandleTranslationUnit(ASTContext &C) override; 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric void ReplaceStmt(Stmt *Old, Stmt *New) { 2520b57cec5SDimitry Andric ReplaceStmtWithRange(Old, New, Old->getSourceRange()); 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { 2560b57cec5SDimitry Andric assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's"); 2570b57cec5SDimitry Andric 2580b57cec5SDimitry Andric Stmt *ReplacingStmt = ReplacedNodes[Old]; 2590b57cec5SDimitry Andric if (ReplacingStmt) 2600b57cec5SDimitry Andric return; // We can't rewrite the same node twice. 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric if (DisableReplaceStmt) 2630b57cec5SDimitry Andric return; 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric // Measure the old text. 2660b57cec5SDimitry Andric int Size = Rewrite.getRangeSize(SrcRange); 2670b57cec5SDimitry Andric if (Size == -1) { 2680b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag) 2690b57cec5SDimitry Andric << Old->getSourceRange(); 2700b57cec5SDimitry Andric return; 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric // Get the new text. 2730b57cec5SDimitry Andric std::string SStr; 2740b57cec5SDimitry Andric llvm::raw_string_ostream S(SStr); 2750b57cec5SDimitry Andric New->printPretty(S, nullptr, PrintingPolicy(LangOpts)); 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // If replacement succeeded or warning disabled return with no warning. 278*0fca6ea1SDimitry Andric if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, SStr)) { 2790b57cec5SDimitry Andric ReplacedNodes[Old] = New; 2800b57cec5SDimitry Andric return; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric if (SilenceRewriteMacroWarning) 2830b57cec5SDimitry Andric return; 2840b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag) 2850b57cec5SDimitry Andric << Old->getSourceRange(); 2860b57cec5SDimitry Andric } 2870b57cec5SDimitry Andric 2880b57cec5SDimitry Andric void InsertText(SourceLocation Loc, StringRef Str, 2890b57cec5SDimitry Andric bool InsertAfter = true) { 2900b57cec5SDimitry Andric // If insertion succeeded or warning disabled return with no warning. 2910b57cec5SDimitry Andric if (!Rewrite.InsertText(Loc, Str, InsertAfter) || 2920b57cec5SDimitry Andric SilenceRewriteMacroWarning) 2930b57cec5SDimitry Andric return; 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric void ReplaceText(SourceLocation Start, unsigned OrigLength, 2990b57cec5SDimitry Andric StringRef Str) { 3000b57cec5SDimitry Andric // If removal succeeded or warning disabled return with no warning. 3010b57cec5SDimitry Andric if (!Rewrite.ReplaceText(Start, OrigLength, Str) || 3020b57cec5SDimitry Andric SilenceRewriteMacroWarning) 3030b57cec5SDimitry Andric return; 3040b57cec5SDimitry Andric 3050b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric // Syntactic Rewriting. 3090b57cec5SDimitry Andric void RewriteRecordBody(RecordDecl *RD); 3100b57cec5SDimitry Andric void RewriteInclude(); 3110b57cec5SDimitry Andric void RewriteLineDirective(const Decl *D); 3120b57cec5SDimitry Andric void ConvertSourceLocationToLineDirective(SourceLocation Loc, 3130b57cec5SDimitry Andric std::string &LineString); 3140b57cec5SDimitry Andric void RewriteForwardClassDecl(DeclGroupRef D); 3150b57cec5SDimitry Andric void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG); 3160b57cec5SDimitry Andric void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 3170b57cec5SDimitry Andric const std::string &typedefString); 3180b57cec5SDimitry Andric void RewriteImplementations(); 3190b57cec5SDimitry Andric void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 3200b57cec5SDimitry Andric ObjCImplementationDecl *IMD, 3210b57cec5SDimitry Andric ObjCCategoryImplDecl *CID); 3220b57cec5SDimitry Andric void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); 3230b57cec5SDimitry Andric void RewriteImplementationDecl(Decl *Dcl); 3240b57cec5SDimitry Andric void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 3250b57cec5SDimitry Andric ObjCMethodDecl *MDecl, std::string &ResultStr); 3260b57cec5SDimitry Andric void RewriteTypeIntoString(QualType T, std::string &ResultStr, 3270b57cec5SDimitry Andric const FunctionType *&FPRetType); 3280b57cec5SDimitry Andric void RewriteByRefString(std::string &ResultStr, const std::string &Name, 3290b57cec5SDimitry Andric ValueDecl *VD, bool def=false); 3300b57cec5SDimitry Andric void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); 3310b57cec5SDimitry Andric void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); 3320b57cec5SDimitry Andric void RewriteForwardProtocolDecl(DeclGroupRef D); 3330b57cec5SDimitry Andric void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG); 3340b57cec5SDimitry Andric void RewriteMethodDeclaration(ObjCMethodDecl *Method); 3350b57cec5SDimitry Andric void RewriteProperty(ObjCPropertyDecl *prop); 3360b57cec5SDimitry Andric void RewriteFunctionDecl(FunctionDecl *FD); 3370b57cec5SDimitry Andric void RewriteBlockPointerType(std::string& Str, QualType Type); 3380b57cec5SDimitry Andric void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD); 3390b57cec5SDimitry Andric void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); 3400b57cec5SDimitry Andric void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); 3410b57cec5SDimitry Andric void RewriteTypeOfDecl(VarDecl *VD); 3420b57cec5SDimitry Andric void RewriteObjCQualifiedInterfaceTypes(Expr *E); 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric std::string getIvarAccessString(ObjCIvarDecl *D); 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric // Expression Rewriting. 3470b57cec5SDimitry Andric Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); 3480b57cec5SDimitry Andric Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); 3490b57cec5SDimitry Andric Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo); 3500b57cec5SDimitry Andric Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo); 3510b57cec5SDimitry Andric Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); 3520b57cec5SDimitry Andric Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); 3530b57cec5SDimitry Andric Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); 3540b57cec5SDimitry Andric Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp); 3550b57cec5SDimitry Andric Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp); 3560b57cec5SDimitry Andric Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp); 3570b57cec5SDimitry Andric Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp); 3580b57cec5SDimitry Andric Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); 3590b57cec5SDimitry Andric Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); 3600b57cec5SDimitry Andric Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); 3610b57cec5SDimitry Andric Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); 3620b57cec5SDimitry Andric Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); 3630b57cec5SDimitry Andric Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 3640b57cec5SDimitry Andric SourceLocation OrigEnd); 3650b57cec5SDimitry Andric Stmt *RewriteBreakStmt(BreakStmt *S); 3660b57cec5SDimitry Andric Stmt *RewriteContinueStmt(ContinueStmt *S); 3670b57cec5SDimitry Andric void RewriteCastExpr(CStyleCastExpr *CE); 3680b57cec5SDimitry Andric void RewriteImplicitCastObjCExpr(CastExpr *IE); 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric // Computes ivar bitfield group no. 3710b57cec5SDimitry Andric unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV); 3720b57cec5SDimitry Andric // Names field decl. for ivar bitfield group. 3730b57cec5SDimitry Andric void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result); 3740b57cec5SDimitry Andric // Names struct type for ivar bitfield group. 3750b57cec5SDimitry Andric void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result); 3760b57cec5SDimitry Andric // Names symbol for ivar bitfield group field offset. 3770b57cec5SDimitry Andric void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result); 3780b57cec5SDimitry Andric // Given an ivar bitfield, it builds (or finds) its group record type. 3790b57cec5SDimitry Andric QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV); 3800b57cec5SDimitry Andric QualType SynthesizeBitfieldGroupStructType( 3810b57cec5SDimitry Andric ObjCIvarDecl *IV, 3820b57cec5SDimitry Andric SmallVectorImpl<ObjCIvarDecl *> &IVars); 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric // Block rewriting. 3850b57cec5SDimitry Andric void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric // Block specific rewrite rules. 3880b57cec5SDimitry Andric void RewriteBlockPointerDecl(NamedDecl *VD); 3890b57cec5SDimitry Andric void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl); 3900b57cec5SDimitry Andric Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD); 3910b57cec5SDimitry Andric Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); 3920b57cec5SDimitry Andric void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 3950b57cec5SDimitry Andric std::string &Result); 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result); 3980b57cec5SDimitry Andric bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag, 3990b57cec5SDimitry Andric bool &IsNamedDefinition); 4000b57cec5SDimitry Andric void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl, 4010b57cec5SDimitry Andric std::string &Result); 4020b57cec5SDimitry Andric 4030b57cec5SDimitry Andric bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result); 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, 4060b57cec5SDimitry Andric std::string &Result); 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric void Initialize(ASTContext &context) override; 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric // Misc. AST transformation routines. Sometimes they end up calling 4110b57cec5SDimitry Andric // rewriting routines on the new ASTs. 4120b57cec5SDimitry Andric CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 4130b57cec5SDimitry Andric ArrayRef<Expr *> Args, 4140b57cec5SDimitry Andric SourceLocation StartLoc=SourceLocation(), 4150b57cec5SDimitry Andric SourceLocation EndLoc=SourceLocation()); 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, 4180b57cec5SDimitry Andric QualType returnType, 4190b57cec5SDimitry Andric SmallVectorImpl<QualType> &ArgTypes, 4200b57cec5SDimitry Andric SmallVectorImpl<Expr*> &MsgExprs, 4210b57cec5SDimitry Andric ObjCMethodDecl *Method); 4220b57cec5SDimitry Andric 4230b57cec5SDimitry Andric Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, 4240b57cec5SDimitry Andric SourceLocation StartLoc=SourceLocation(), 4250b57cec5SDimitry Andric SourceLocation EndLoc=SourceLocation()); 4260b57cec5SDimitry Andric 4270b57cec5SDimitry Andric void SynthCountByEnumWithState(std::string &buf); 4280b57cec5SDimitry Andric void SynthMsgSendFunctionDecl(); 4290b57cec5SDimitry Andric void SynthMsgSendSuperFunctionDecl(); 4300b57cec5SDimitry Andric void SynthMsgSendStretFunctionDecl(); 4310b57cec5SDimitry Andric void SynthMsgSendFpretFunctionDecl(); 4320b57cec5SDimitry Andric void SynthMsgSendSuperStretFunctionDecl(); 4330b57cec5SDimitry Andric void SynthGetClassFunctionDecl(); 4340b57cec5SDimitry Andric void SynthGetMetaClassFunctionDecl(); 4350b57cec5SDimitry Andric void SynthGetSuperClassFunctionDecl(); 4360b57cec5SDimitry Andric void SynthSelGetUidFunctionDecl(); 4370b57cec5SDimitry Andric void SynthSuperConstructorFunctionDecl(); 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric // Rewriting metadata 4400b57cec5SDimitry Andric template<typename MethodIterator> 4410b57cec5SDimitry Andric void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 4420b57cec5SDimitry Andric MethodIterator MethodEnd, 4430b57cec5SDimitry Andric bool IsInstanceMethod, 4440b57cec5SDimitry Andric StringRef prefix, 4450b57cec5SDimitry Andric StringRef ClassName, 4460b57cec5SDimitry Andric std::string &Result); 4470b57cec5SDimitry Andric void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 4480b57cec5SDimitry Andric std::string &Result); 4490b57cec5SDimitry Andric void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 4500b57cec5SDimitry Andric std::string &Result); 4510b57cec5SDimitry Andric void RewriteClassSetupInitHook(std::string &Result); 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric void RewriteMetaDataIntoBuffer(std::string &Result); 4540b57cec5SDimitry Andric void WriteImageInfo(std::string &Result); 4550b57cec5SDimitry Andric void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 4560b57cec5SDimitry Andric std::string &Result); 4570b57cec5SDimitry Andric void RewriteCategorySetupInitHook(std::string &Result); 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric // Rewriting ivar 4600b57cec5SDimitry Andric void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 4610b57cec5SDimitry Andric std::string &Result); 4620b57cec5SDimitry Andric Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV); 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); 4660b57cec5SDimitry Andric std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 467*0fca6ea1SDimitry Andric StringRef funcName, 468*0fca6ea1SDimitry Andric const std::string &Tag); 469*0fca6ea1SDimitry Andric std::string SynthesizeBlockFunc(BlockExpr *CE, int i, StringRef funcName, 470*0fca6ea1SDimitry Andric const std::string &Tag); 471*0fca6ea1SDimitry Andric std::string SynthesizeBlockImpl(BlockExpr *CE, const std::string &Tag, 472*0fca6ea1SDimitry Andric const std::string &Desc); 473*0fca6ea1SDimitry Andric std::string SynthesizeBlockDescriptor(const std::string &DescTag, 474*0fca6ea1SDimitry Andric const std::string &ImplTag, int i, 475*0fca6ea1SDimitry Andric StringRef funcName, unsigned hasCopy); 4760b57cec5SDimitry Andric Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); 4770b57cec5SDimitry Andric void SynthesizeBlockLiterals(SourceLocation FunLocStart, 4780b57cec5SDimitry Andric StringRef FunName); 4790b57cec5SDimitry Andric FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); 4800b57cec5SDimitry Andric Stmt *SynthBlockInitExpr(BlockExpr *Exp, 4810b57cec5SDimitry Andric const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs); 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric // Misc. helper routines. 4840b57cec5SDimitry Andric QualType getProtocolType(); 4850b57cec5SDimitry Andric void WarnAboutReturnGotoStmts(Stmt *S); 4860b57cec5SDimitry Andric void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); 4870b57cec5SDimitry Andric void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); 4880b57cec5SDimitry Andric void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric bool IsDeclStmtInForeachHeader(DeclStmt *DS); 4910b57cec5SDimitry Andric void CollectBlockDeclRefInfo(BlockExpr *Exp); 4920b57cec5SDimitry Andric void GetBlockDeclRefExprs(Stmt *S); 4930b57cec5SDimitry Andric void GetInnerBlockDeclRefExprs(Stmt *S, 4940b57cec5SDimitry Andric SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs, 4950b57cec5SDimitry Andric llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts); 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric // We avoid calling Type::isBlockPointerType(), since it operates on the 4980b57cec5SDimitry Andric // canonical type. We only care if the top-level type is a closure pointer. 4990b57cec5SDimitry Andric bool isTopLevelBlockPointerType(QualType T) { 5000b57cec5SDimitry Andric return isa<BlockPointerType>(T); 5010b57cec5SDimitry Andric } 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric /// convertBlockPointerToFunctionPointer - Converts a block-pointer type 5040b57cec5SDimitry Andric /// to a function pointer type and upon success, returns true; false 5050b57cec5SDimitry Andric /// otherwise. 5060b57cec5SDimitry Andric bool convertBlockPointerToFunctionPointer(QualType &T) { 5070b57cec5SDimitry Andric if (isTopLevelBlockPointerType(T)) { 508a7dea167SDimitry Andric const auto *BPT = T->castAs<BlockPointerType>(); 5090b57cec5SDimitry Andric T = Context->getPointerType(BPT->getPointeeType()); 5100b57cec5SDimitry Andric return true; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric return false; 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric bool convertObjCTypeToCStyleType(QualType &T); 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric bool needToScanForQualifiers(QualType T); 5180b57cec5SDimitry Andric QualType getSuperStructType(); 5190b57cec5SDimitry Andric QualType getConstantStringStructType(); 5200b57cec5SDimitry Andric QualType convertFunctionTypeOfBlocks(const FunctionType *FT); 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric void convertToUnqualifiedObjCType(QualType &T) { 5230b57cec5SDimitry Andric if (T->isObjCQualifiedIdType()) { 5240b57cec5SDimitry Andric bool isConst = T.isConstQualified(); 5250b57cec5SDimitry Andric T = isConst ? Context->getObjCIdType().withConst() 5260b57cec5SDimitry Andric : Context->getObjCIdType(); 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric else if (T->isObjCQualifiedClassType()) 5290b57cec5SDimitry Andric T = Context->getObjCClassType(); 5300b57cec5SDimitry Andric else if (T->isObjCObjectPointerType() && 5310b57cec5SDimitry Andric T->getPointeeType()->isObjCQualifiedInterfaceType()) { 5320b57cec5SDimitry Andric if (const ObjCObjectPointerType * OBJPT = 5330b57cec5SDimitry Andric T->getAsObjCInterfacePointerType()) { 5340b57cec5SDimitry Andric const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); 5350b57cec5SDimitry Andric T = QualType(IFaceT, 0); 5360b57cec5SDimitry Andric T = Context->getPointerType(T); 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric // FIXME: This predicate seems like it would be useful to add to ASTContext. 5420b57cec5SDimitry Andric bool isObjCType(QualType T) { 5430b57cec5SDimitry Andric if (!LangOpts.ObjC) 5440b57cec5SDimitry Andric return false; 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || 5490b57cec5SDimitry Andric OCT == Context->getCanonicalType(Context->getObjCClassType())) 5500b57cec5SDimitry Andric return true; 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric if (const PointerType *PT = OCT->getAs<PointerType>()) { 5530b57cec5SDimitry Andric if (isa<ObjCInterfaceType>(PT->getPointeeType()) || 5540b57cec5SDimitry Andric PT->getPointeeType()->isObjCQualifiedIdType()) 5550b57cec5SDimitry Andric return true; 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric return false; 5580b57cec5SDimitry Andric } 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric bool PointerTypeTakesAnyBlockArguments(QualType QT); 5610b57cec5SDimitry Andric bool PointerTypeTakesAnyObjCQualifiedType(QualType QT); 5620b57cec5SDimitry Andric void GetExtentOfArgList(const char *Name, const char *&LParen, 5630b57cec5SDimitry Andric const char *&RParen); 5640b57cec5SDimitry Andric 5650b57cec5SDimitry Andric void QuoteDoublequotes(std::string &From, std::string &To) { 5660b57cec5SDimitry Andric for (unsigned i = 0; i < From.length(); i++) { 5670b57cec5SDimitry Andric if (From[i] == '"') 5680b57cec5SDimitry Andric To += "\\\""; 5690b57cec5SDimitry Andric else 5700b57cec5SDimitry Andric To += From[i]; 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric QualType getSimpleFunctionType(QualType result, 5750b57cec5SDimitry Andric ArrayRef<QualType> args, 5760b57cec5SDimitry Andric bool variadic = false) { 5770b57cec5SDimitry Andric if (result == Context->getObjCInstanceType()) 5780b57cec5SDimitry Andric result = Context->getObjCIdType(); 5790b57cec5SDimitry Andric FunctionProtoType::ExtProtoInfo fpi; 5800b57cec5SDimitry Andric fpi.Variadic = variadic; 5810b57cec5SDimitry Andric return Context->getFunctionType(result, args, fpi); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric // Helper function: create a CStyleCastExpr with trivial type source info. 5850b57cec5SDimitry Andric CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, 5860b57cec5SDimitry Andric CastKind Kind, Expr *E) { 5870b57cec5SDimitry Andric TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); 588fe6060f1SDimitry Andric return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr, 589e8d8bef9SDimitry Andric FPOptionsOverride(), TInfo, 590e8d8bef9SDimitry Andric SourceLocation(), SourceLocation()); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const { 594*0fca6ea1SDimitry Andric const IdentifierInfo *II = &Context->Idents.get("load"); 5950b57cec5SDimitry Andric Selector LoadSel = Context->Selectors.getSelector(0, &II); 5960b57cec5SDimitry Andric return OD->getClassMethod(LoadSel) != nullptr; 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric StringLiteral *getStringLiteral(StringRef Str) { 6000b57cec5SDimitry Andric QualType StrType = Context->getConstantArrayType( 601a7dea167SDimitry Andric Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr, 6025f757f3fSDimitry Andric ArraySizeModifier::Normal, 0); 6035f757f3fSDimitry Andric return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary, 6040b57cec5SDimitry Andric /*Pascal=*/false, StrType, SourceLocation()); 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric }; 6070b57cec5SDimitry Andric } // end anonymous namespace 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType, 6100b57cec5SDimitry Andric NamedDecl *D) { 6110b57cec5SDimitry Andric if (const FunctionProtoType *fproto 6120b57cec5SDimitry Andric = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) { 6130b57cec5SDimitry Andric for (const auto &I : fproto->param_types()) 6140b57cec5SDimitry Andric if (isTopLevelBlockPointerType(I)) { 6150b57cec5SDimitry Andric // All the args are checked/rewritten. Don't call twice! 6160b57cec5SDimitry Andric RewriteBlockPointerDecl(D); 6170b57cec5SDimitry Andric break; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { 6230b57cec5SDimitry Andric const PointerType *PT = funcType->getAs<PointerType>(); 6240b57cec5SDimitry Andric if (PT && PointerTypeTakesAnyBlockArguments(funcType)) 6250b57cec5SDimitry Andric RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric static bool IsHeaderFile(const std::string &Filename) { 6290b57cec5SDimitry Andric std::string::size_type DotPos = Filename.rfind('.'); 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric if (DotPos == std::string::npos) { 6320b57cec5SDimitry Andric // no file extension 6330b57cec5SDimitry Andric return false; 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6364824e7fdSDimitry Andric std::string Ext = Filename.substr(DotPos + 1); 6370b57cec5SDimitry Andric // C header: .h 6380b57cec5SDimitry Andric // C++ header: .hh or .H; 6390b57cec5SDimitry Andric return Ext == "h" || Ext == "hh" || Ext == "H"; 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric 6420b57cec5SDimitry Andric RewriteModernObjC::RewriteModernObjC(std::string inFile, 6430b57cec5SDimitry Andric std::unique_ptr<raw_ostream> OS, 6440b57cec5SDimitry Andric DiagnosticsEngine &D, 6450b57cec5SDimitry Andric const LangOptions &LOpts, 6460b57cec5SDimitry Andric bool silenceMacroWarn, bool LineInfo) 6470b57cec5SDimitry Andric : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)), 6480b57cec5SDimitry Andric SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) { 6490b57cec5SDimitry Andric IsHeader = IsHeaderFile(inFile); 6500b57cec5SDimitry Andric RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 6510b57cec5SDimitry Andric "rewriting sub-expression within a macro (may not be correct)"); 6520b57cec5SDimitry Andric // FIXME. This should be an error. But if block is not called, it is OK. And it 6530b57cec5SDimitry Andric // may break including some headers. 6540b57cec5SDimitry Andric GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 6550b57cec5SDimitry Andric "rewriting block literal declared in global scope is not implemented"); 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric TryFinallyContainsReturnDiag = Diags.getCustomDiagID( 6580b57cec5SDimitry Andric DiagnosticsEngine::Warning, 6590b57cec5SDimitry Andric "rewriter doesn't support user-specified control flow semantics " 6600b57cec5SDimitry Andric "for @try/@finally (code may not execute properly)"); 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter( 6640b57cec5SDimitry Andric const std::string &InFile, std::unique_ptr<raw_ostream> OS, 6650b57cec5SDimitry Andric DiagnosticsEngine &Diags, const LangOptions &LOpts, 6660b57cec5SDimitry Andric bool SilenceRewriteMacroWarning, bool LineInfo) { 667a7dea167SDimitry Andric return std::make_unique<RewriteModernObjC>(InFile, std::move(OS), Diags, 6680b57cec5SDimitry Andric LOpts, SilenceRewriteMacroWarning, 6690b57cec5SDimitry Andric LineInfo); 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric void RewriteModernObjC::InitializeCommon(ASTContext &context) { 6730b57cec5SDimitry Andric Context = &context; 6740b57cec5SDimitry Andric SM = &Context->getSourceManager(); 6750b57cec5SDimitry Andric TUDecl = Context->getTranslationUnitDecl(); 6760b57cec5SDimitry Andric MsgSendFunctionDecl = nullptr; 6770b57cec5SDimitry Andric MsgSendSuperFunctionDecl = nullptr; 6780b57cec5SDimitry Andric MsgSendStretFunctionDecl = nullptr; 6790b57cec5SDimitry Andric MsgSendSuperStretFunctionDecl = nullptr; 6800b57cec5SDimitry Andric MsgSendFpretFunctionDecl = nullptr; 6810b57cec5SDimitry Andric GetClassFunctionDecl = nullptr; 6820b57cec5SDimitry Andric GetMetaClassFunctionDecl = nullptr; 6830b57cec5SDimitry Andric GetSuperClassFunctionDecl = nullptr; 6840b57cec5SDimitry Andric SelGetUidFunctionDecl = nullptr; 6850b57cec5SDimitry Andric CFStringFunctionDecl = nullptr; 6860b57cec5SDimitry Andric ConstantStringClassReference = nullptr; 6870b57cec5SDimitry Andric NSStringRecord = nullptr; 6880b57cec5SDimitry Andric CurMethodDef = nullptr; 6890b57cec5SDimitry Andric CurFunctionDef = nullptr; 6900b57cec5SDimitry Andric GlobalVarDecl = nullptr; 6910b57cec5SDimitry Andric GlobalConstructionExp = nullptr; 6920b57cec5SDimitry Andric SuperStructDecl = nullptr; 6930b57cec5SDimitry Andric ProtocolTypeDecl = nullptr; 6940b57cec5SDimitry Andric ConstantStringDecl = nullptr; 6950b57cec5SDimitry Andric BcLabelCount = 0; 6960b57cec5SDimitry Andric SuperConstructorFunctionDecl = nullptr; 6970b57cec5SDimitry Andric NumObjCStringLiterals = 0; 6980b57cec5SDimitry Andric PropParentMap = nullptr; 6990b57cec5SDimitry Andric CurrentBody = nullptr; 7000b57cec5SDimitry Andric DisableReplaceStmt = false; 7010b57cec5SDimitry Andric objc_impl_method = false; 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric // Get the ID and start/end of the main file. 7040b57cec5SDimitry Andric MainFileID = SM->getMainFileID(); 705e8d8bef9SDimitry Andric llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID); 706e8d8bef9SDimitry Andric MainFileStart = MainBuf.getBufferStart(); 707e8d8bef9SDimitry Andric MainFileEnd = MainBuf.getBufferEnd(); 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts()); 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7130b57cec5SDimitry Andric // Top Level Driver Code 7140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) { 7170b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 7180b57cec5SDimitry Andric return; 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric // Two cases: either the decl could be in the main file, or it could be in a 7210b57cec5SDimitry Andric // #included file. If the former, rewrite it now. If the later, check to see 7220b57cec5SDimitry Andric // if we rewrote the #include/#import. 7230b57cec5SDimitry Andric SourceLocation Loc = D->getLocation(); 7240b57cec5SDimitry Andric Loc = SM->getExpansionLoc(Loc); 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric // If this is for a builtin, ignore it. 7270b57cec5SDimitry Andric if (Loc.isInvalid()) return; 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric // Look for built-in declarations that we need to refer during the rewrite. 7300b57cec5SDimitry Andric if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 7310b57cec5SDimitry Andric RewriteFunctionDecl(FD); 7320b57cec5SDimitry Andric } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) { 7330b57cec5SDimitry Andric // declared in <Foundation/NSString.h> 7340b57cec5SDimitry Andric if (FVD->getName() == "_NSConstantStringClassReference") { 7350b57cec5SDimitry Andric ConstantStringClassReference = FVD; 7360b57cec5SDimitry Andric return; 7370b57cec5SDimitry Andric } 7380b57cec5SDimitry Andric } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { 7390b57cec5SDimitry Andric RewriteCategoryDecl(CD); 7400b57cec5SDimitry Andric } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { 7410b57cec5SDimitry Andric if (PD->isThisDeclarationADefinition()) 7420b57cec5SDimitry Andric RewriteProtocolDecl(PD); 7430b57cec5SDimitry Andric } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { 7440b57cec5SDimitry Andric // Recurse into linkage specifications 7450b57cec5SDimitry Andric for (DeclContext::decl_iterator DI = LSD->decls_begin(), 7460b57cec5SDimitry Andric DIEnd = LSD->decls_end(); 7470b57cec5SDimitry Andric DI != DIEnd; ) { 7480b57cec5SDimitry Andric if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) { 7490b57cec5SDimitry Andric if (!IFace->isThisDeclarationADefinition()) { 7500b57cec5SDimitry Andric SmallVector<Decl *, 8> DG; 7510b57cec5SDimitry Andric SourceLocation StartLoc = IFace->getBeginLoc(); 7520b57cec5SDimitry Andric do { 7530b57cec5SDimitry Andric if (isa<ObjCInterfaceDecl>(*DI) && 7540b57cec5SDimitry Andric !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() && 7550b57cec5SDimitry Andric StartLoc == (*DI)->getBeginLoc()) 7560b57cec5SDimitry Andric DG.push_back(*DI); 7570b57cec5SDimitry Andric else 7580b57cec5SDimitry Andric break; 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric ++DI; 7610b57cec5SDimitry Andric } while (DI != DIEnd); 7620b57cec5SDimitry Andric RewriteForwardClassDecl(DG); 7630b57cec5SDimitry Andric continue; 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric else { 7660b57cec5SDimitry Andric // Keep track of all interface declarations seen. 7670b57cec5SDimitry Andric ObjCInterfacesSeen.push_back(IFace); 7680b57cec5SDimitry Andric ++DI; 7690b57cec5SDimitry Andric continue; 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) { 7740b57cec5SDimitry Andric if (!Proto->isThisDeclarationADefinition()) { 7750b57cec5SDimitry Andric SmallVector<Decl *, 8> DG; 7760b57cec5SDimitry Andric SourceLocation StartLoc = Proto->getBeginLoc(); 7770b57cec5SDimitry Andric do { 7780b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(*DI) && 7790b57cec5SDimitry Andric !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() && 7800b57cec5SDimitry Andric StartLoc == (*DI)->getBeginLoc()) 7810b57cec5SDimitry Andric DG.push_back(*DI); 7820b57cec5SDimitry Andric else 7830b57cec5SDimitry Andric break; 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric ++DI; 7860b57cec5SDimitry Andric } while (DI != DIEnd); 7870b57cec5SDimitry Andric RewriteForwardProtocolDecl(DG); 7880b57cec5SDimitry Andric continue; 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric } 7910b57cec5SDimitry Andric 7920b57cec5SDimitry Andric HandleTopLevelSingleDecl(*DI); 7930b57cec5SDimitry Andric ++DI; 7940b57cec5SDimitry Andric } 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric // If we have a decl in the main file, see if we should rewrite it. 7970b57cec5SDimitry Andric if (SM->isWrittenInMainFile(Loc)) 7980b57cec5SDimitry Andric return HandleDeclInMainFile(D); 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8020b57cec5SDimitry Andric // Syntactic (non-AST) Rewriting Code 8030b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric void RewriteModernObjC::RewriteInclude() { 8060b57cec5SDimitry Andric SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); 8070b57cec5SDimitry Andric StringRef MainBuf = SM->getBufferData(MainFileID); 8080b57cec5SDimitry Andric const char *MainBufStart = MainBuf.begin(); 8090b57cec5SDimitry Andric const char *MainBufEnd = MainBuf.end(); 8100b57cec5SDimitry Andric size_t ImportLen = strlen("import"); 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric // Loop over the whole file, looking for includes. 8130b57cec5SDimitry Andric for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { 8140b57cec5SDimitry Andric if (*BufPtr == '#') { 8150b57cec5SDimitry Andric if (++BufPtr == MainBufEnd) 8160b57cec5SDimitry Andric return; 8170b57cec5SDimitry Andric while (*BufPtr == ' ' || *BufPtr == '\t') 8180b57cec5SDimitry Andric if (++BufPtr == MainBufEnd) 8190b57cec5SDimitry Andric return; 8200b57cec5SDimitry Andric if (!strncmp(BufPtr, "import", ImportLen)) { 8210b57cec5SDimitry Andric // replace import with include 8220b57cec5SDimitry Andric SourceLocation ImportLoc = 8230b57cec5SDimitry Andric LocStart.getLocWithOffset(BufPtr-MainBufStart); 8240b57cec5SDimitry Andric ReplaceText(ImportLoc, ImportLen, "include"); 8250b57cec5SDimitry Andric BufPtr += ImportLen; 8260b57cec5SDimitry Andric } 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric } 8290b57cec5SDimitry Andric } 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl, 8320b57cec5SDimitry Andric ObjCIvarDecl *IvarDecl, std::string &Result) { 8330b57cec5SDimitry Andric Result += "OBJC_IVAR_$_"; 8340b57cec5SDimitry Andric Result += IDecl->getName(); 8350b57cec5SDimitry Andric Result += "$"; 8360b57cec5SDimitry Andric Result += IvarDecl->getName(); 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric std::string 8400b57cec5SDimitry Andric RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { 8410b57cec5SDimitry Andric const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface(); 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric // Build name of symbol holding ivar offset. 8440b57cec5SDimitry Andric std::string IvarOffsetName; 8450b57cec5SDimitry Andric if (D->isBitField()) 8460b57cec5SDimitry Andric ObjCIvarBitfieldGroupOffset(D, IvarOffsetName); 8470b57cec5SDimitry Andric else 8480b57cec5SDimitry Andric WriteInternalIvarName(ClassDecl, D, IvarOffsetName); 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric std::string S = "(*("; 8510b57cec5SDimitry Andric QualType IvarT = D->getType(); 8520b57cec5SDimitry Andric if (D->isBitField()) 8530b57cec5SDimitry Andric IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); 8540b57cec5SDimitry Andric 855bdd1243dSDimitry Andric if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) { 856a7dea167SDimitry Andric RecordDecl *RD = IvarT->castAs<RecordType>()->getDecl(); 8570b57cec5SDimitry Andric RD = RD->getDefinition(); 8580b57cec5SDimitry Andric if (RD && !RD->getDeclName().getAsIdentifierInfo()) { 8590b57cec5SDimitry Andric // decltype(((Foo_IMPL*)0)->bar) * 860a7dea167SDimitry Andric auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext()); 8610b57cec5SDimitry Andric // ivar in class extensions requires special treatment. 8620b57cec5SDimitry Andric if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 8630b57cec5SDimitry Andric CDecl = CatDecl->getClassInterface(); 8645ffd83dbSDimitry Andric std::string RecName = std::string(CDecl->getName()); 8650b57cec5SDimitry Andric RecName += "_IMPL"; 8665f757f3fSDimitry Andric RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 8675f757f3fSDimitry Andric SourceLocation(), SourceLocation(), 8685f757f3fSDimitry Andric &Context->Idents.get(RecName)); 8690b57cec5SDimitry Andric QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD)); 8700b57cec5SDimitry Andric unsigned UnsignedIntSize = 8710b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 8720b57cec5SDimitry Andric Expr *Zero = IntegerLiteral::Create(*Context, 8730b57cec5SDimitry Andric llvm::APInt(UnsignedIntSize, 0), 8740b57cec5SDimitry Andric Context->UnsignedIntTy, SourceLocation()); 8750b57cec5SDimitry Andric Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero); 8760b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 8770b57cec5SDimitry Andric Zero); 8780b57cec5SDimitry Andric FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 8790b57cec5SDimitry Andric SourceLocation(), 8800b57cec5SDimitry Andric &Context->Idents.get(D->getNameAsString()), 8810b57cec5SDimitry Andric IvarT, nullptr, 8820b57cec5SDimitry Andric /*BitWidth=*/nullptr, /*Mutable=*/true, 8830b57cec5SDimitry Andric ICIS_NoInit); 8840b57cec5SDimitry Andric MemberExpr *ME = MemberExpr::CreateImplicit( 8850b57cec5SDimitry Andric *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); 8860b57cec5SDimitry Andric IvarT = Context->getDecltypeType(ME, ME->getType()); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric } 8890b57cec5SDimitry Andric convertObjCTypeToCStyleType(IvarT); 8900b57cec5SDimitry Andric QualType castT = Context->getPointerType(IvarT); 8910b57cec5SDimitry Andric std::string TypeString(castT.getAsString(Context->getPrintingPolicy())); 8920b57cec5SDimitry Andric S += TypeString; 8930b57cec5SDimitry Andric S += ")"; 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric // ((char *)self + IVAR_OFFSET_SYMBOL_NAME) 8960b57cec5SDimitry Andric S += "((char *)self + "; 8970b57cec5SDimitry Andric S += IvarOffsetName; 8980b57cec5SDimitry Andric S += "))"; 8990b57cec5SDimitry Andric if (D->isBitField()) { 9000b57cec5SDimitry Andric S += "."; 9010b57cec5SDimitry Andric S += D->getNameAsString(); 9020b57cec5SDimitry Andric } 9030b57cec5SDimitry Andric ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D); 9040b57cec5SDimitry Andric return S; 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric 9070b57cec5SDimitry Andric /// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not 9080b57cec5SDimitry Andric /// been found in the class implementation. In this case, it must be synthesized. 9090b57cec5SDimitry Andric static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP, 9100b57cec5SDimitry Andric ObjCPropertyDecl *PD, 9110b57cec5SDimitry Andric bool getter) { 912480093f4SDimitry Andric auto *OMD = IMP->getInstanceMethod(getter ? PD->getGetterName() 913480093f4SDimitry Andric : PD->getSetterName()); 914480093f4SDimitry Andric return !OMD || OMD->isSynthesizedAccessorStub(); 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 9180b57cec5SDimitry Andric ObjCImplementationDecl *IMD, 9190b57cec5SDimitry Andric ObjCCategoryImplDecl *CID) { 9200b57cec5SDimitry Andric static bool objcGetPropertyDefined = false; 9210b57cec5SDimitry Andric static bool objcSetPropertyDefined = false; 9220b57cec5SDimitry Andric SourceLocation startGetterSetterLoc; 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric if (PID->getBeginLoc().isValid()) { 9250b57cec5SDimitry Andric SourceLocation startLoc = PID->getBeginLoc(); 9260b57cec5SDimitry Andric InsertText(startLoc, "// "); 9270b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 9280b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @synthesize location"); 9290b57cec5SDimitry Andric const char *semiBuf = strchr(startBuf, ';'); 9300b57cec5SDimitry Andric assert((*semiBuf == ';') && "@synthesize: can't find ';'"); 9310b57cec5SDimitry Andric startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 9320b57cec5SDimitry Andric } else 9330b57cec5SDimitry Andric startGetterSetterLoc = IMD ? IMD->getEndLoc() : CID->getEndLoc(); 9340b57cec5SDimitry Andric 9350b57cec5SDimitry Andric if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 9360b57cec5SDimitry Andric return; // FIXME: is this correct? 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric // Generate the 'getter' function. 9390b57cec5SDimitry Andric ObjCPropertyDecl *PD = PID->getPropertyDecl(); 9400b57cec5SDimitry Andric ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); 9410b57cec5SDimitry Andric assert(IMD && OID && "Synthesized ivars must be attached to @implementation"); 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric unsigned Attributes = PD->getPropertyAttributes(); 9440b57cec5SDimitry Andric if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) { 9455ffd83dbSDimitry Andric bool GenGetProperty = 9465ffd83dbSDimitry Andric !(Attributes & ObjCPropertyAttribute::kind_nonatomic) && 9475ffd83dbSDimitry Andric (Attributes & (ObjCPropertyAttribute::kind_retain | 9485ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_copy)); 9490b57cec5SDimitry Andric std::string Getr; 9500b57cec5SDimitry Andric if (GenGetProperty && !objcGetPropertyDefined) { 9510b57cec5SDimitry Andric objcGetPropertyDefined = true; 9520b57cec5SDimitry Andric // FIXME. Is this attribute correct in all cases? 9530b57cec5SDimitry Andric Getr = "\nextern \"C\" __declspec(dllimport) " 9540b57cec5SDimitry Andric "id objc_getProperty(id, SEL, long, bool);\n"; 9550b57cec5SDimitry Andric } 9560b57cec5SDimitry Andric RewriteObjCMethodDecl(OID->getContainingInterface(), 957480093f4SDimitry Andric PID->getGetterMethodDecl(), Getr); 9580b57cec5SDimitry Andric Getr += "{ "; 9590b57cec5SDimitry Andric // Synthesize an explicit cast to gain access to the ivar. 9600b57cec5SDimitry Andric // See objc-act.c:objc_synthesize_new_getter() for details. 9610b57cec5SDimitry Andric if (GenGetProperty) { 9620b57cec5SDimitry Andric // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) 9630b57cec5SDimitry Andric Getr += "typedef "; 9640b57cec5SDimitry Andric const FunctionType *FPRetType = nullptr; 965480093f4SDimitry Andric RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr, 9660b57cec5SDimitry Andric FPRetType); 9670b57cec5SDimitry Andric Getr += " _TYPE"; 9680b57cec5SDimitry Andric if (FPRetType) { 9690b57cec5SDimitry Andric Getr += ")"; // close the precedence "scope" for "*". 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric // Now, emit the argument types (if any). 9720b57cec5SDimitry Andric if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){ 9730b57cec5SDimitry Andric Getr += "("; 9740b57cec5SDimitry Andric for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { 9750b57cec5SDimitry Andric if (i) Getr += ", "; 9760b57cec5SDimitry Andric std::string ParamStr = 9770b57cec5SDimitry Andric FT->getParamType(i).getAsString(Context->getPrintingPolicy()); 9780b57cec5SDimitry Andric Getr += ParamStr; 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric if (FT->isVariadic()) { 9810b57cec5SDimitry Andric if (FT->getNumParams()) 9820b57cec5SDimitry Andric Getr += ", "; 9830b57cec5SDimitry Andric Getr += "..."; 9840b57cec5SDimitry Andric } 9850b57cec5SDimitry Andric Getr += ")"; 9860b57cec5SDimitry Andric } else 9870b57cec5SDimitry Andric Getr += "()"; 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric Getr += ";\n"; 9900b57cec5SDimitry Andric Getr += "return (_TYPE)"; 9910b57cec5SDimitry Andric Getr += "objc_getProperty(self, _cmd, "; 9920b57cec5SDimitry Andric RewriteIvarOffsetComputation(OID, Getr); 9930b57cec5SDimitry Andric Getr += ", 1)"; 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric else 9960b57cec5SDimitry Andric Getr += "return " + getIvarAccessString(OID); 9970b57cec5SDimitry Andric Getr += "; }"; 9980b57cec5SDimitry Andric InsertText(startGetterSetterLoc, Getr); 9990b57cec5SDimitry Andric } 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric if (PD->isReadOnly() || 10020b57cec5SDimitry Andric !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/)) 10030b57cec5SDimitry Andric return; 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric // Generate the 'setter' function. 10060b57cec5SDimitry Andric std::string Setr; 10075ffd83dbSDimitry Andric bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain | 10085ffd83dbSDimitry Andric ObjCPropertyAttribute::kind_copy); 10090b57cec5SDimitry Andric if (GenSetProperty && !objcSetPropertyDefined) { 10100b57cec5SDimitry Andric objcSetPropertyDefined = true; 10110b57cec5SDimitry Andric // FIXME. Is this attribute correct in all cases? 10120b57cec5SDimitry Andric Setr = "\nextern \"C\" __declspec(dllimport) " 10130b57cec5SDimitry Andric "void objc_setProperty (id, SEL, long, id, bool, bool);\n"; 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric RewriteObjCMethodDecl(OID->getContainingInterface(), 1017480093f4SDimitry Andric PID->getSetterMethodDecl(), Setr); 10180b57cec5SDimitry Andric Setr += "{ "; 10190b57cec5SDimitry Andric // Synthesize an explicit cast to initialize the ivar. 10200b57cec5SDimitry Andric // See objc-act.c:objc_synthesize_new_setter() for details. 10210b57cec5SDimitry Andric if (GenSetProperty) { 10220b57cec5SDimitry Andric Setr += "objc_setProperty (self, _cmd, "; 10230b57cec5SDimitry Andric RewriteIvarOffsetComputation(OID, Setr); 10240b57cec5SDimitry Andric Setr += ", (id)"; 10250b57cec5SDimitry Andric Setr += PD->getName(); 10260b57cec5SDimitry Andric Setr += ", "; 10275ffd83dbSDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_nonatomic) 10280b57cec5SDimitry Andric Setr += "0, "; 10290b57cec5SDimitry Andric else 10300b57cec5SDimitry Andric Setr += "1, "; 10315ffd83dbSDimitry Andric if (Attributes & ObjCPropertyAttribute::kind_copy) 10320b57cec5SDimitry Andric Setr += "1)"; 10330b57cec5SDimitry Andric else 10340b57cec5SDimitry Andric Setr += "0)"; 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric else { 10370b57cec5SDimitry Andric Setr += getIvarAccessString(OID) + " = "; 10380b57cec5SDimitry Andric Setr += PD->getName(); 10390b57cec5SDimitry Andric } 10400b57cec5SDimitry Andric Setr += "; }\n"; 10410b57cec5SDimitry Andric InsertText(startGetterSetterLoc, Setr); 10420b57cec5SDimitry Andric } 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, 10450b57cec5SDimitry Andric std::string &typedefString) { 10460b57cec5SDimitry Andric typedefString += "\n#ifndef _REWRITER_typedef_"; 10470b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 10480b57cec5SDimitry Andric typedefString += "\n"; 10490b57cec5SDimitry Andric typedefString += "#define _REWRITER_typedef_"; 10500b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 10510b57cec5SDimitry Andric typedefString += "\n"; 10520b57cec5SDimitry Andric typedefString += "typedef struct objc_object "; 10530b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 10540b57cec5SDimitry Andric // typedef struct { } _objc_exc_Classname; 10550b57cec5SDimitry Andric typedefString += ";\ntypedef struct {} _objc_exc_"; 10560b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 10570b57cec5SDimitry Andric typedefString += ";\n#endif\n"; 10580b57cec5SDimitry Andric } 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 10610b57cec5SDimitry Andric const std::string &typedefString) { 10620b57cec5SDimitry Andric SourceLocation startLoc = ClassDecl->getBeginLoc(); 10630b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 10640b57cec5SDimitry Andric const char *semiPtr = strchr(startBuf, ';'); 10650b57cec5SDimitry Andric // Replace the @class with typedefs corresponding to the classes. 10660b57cec5SDimitry Andric ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric 10690b57cec5SDimitry Andric void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) { 10700b57cec5SDimitry Andric std::string typedefString; 10710b57cec5SDimitry Andric for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 10720b57cec5SDimitry Andric if (ObjCInterfaceDecl *ForwardDecl = dyn_cast<ObjCInterfaceDecl>(*I)) { 10730b57cec5SDimitry Andric if (I == D.begin()) { 10740b57cec5SDimitry Andric // Translate to typedef's that forward reference structs with the same name 10750b57cec5SDimitry Andric // as the class. As a convenience, we include the original declaration 10760b57cec5SDimitry Andric // as a comment. 10770b57cec5SDimitry Andric typedefString += "// @class "; 10780b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 10790b57cec5SDimitry Andric typedefString += ";"; 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric RewriteOneForwardClassDecl(ForwardDecl, typedefString); 10820b57cec5SDimitry Andric } 10830b57cec5SDimitry Andric else 10840b57cec5SDimitry Andric HandleTopLevelSingleDecl(*I); 10850b57cec5SDimitry Andric } 10860b57cec5SDimitry Andric DeclGroupRef::iterator I = D.begin(); 10870b57cec5SDimitry Andric RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString); 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric void RewriteModernObjC::RewriteForwardClassDecl( 10910b57cec5SDimitry Andric const SmallVectorImpl<Decl *> &D) { 10920b57cec5SDimitry Andric std::string typedefString; 10930b57cec5SDimitry Andric for (unsigned i = 0; i < D.size(); i++) { 10940b57cec5SDimitry Andric ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]); 10950b57cec5SDimitry Andric if (i == 0) { 10960b57cec5SDimitry Andric typedefString += "// @class "; 10970b57cec5SDimitry Andric typedefString += ForwardDecl->getNameAsString(); 10980b57cec5SDimitry Andric typedefString += ";"; 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric RewriteOneForwardClassDecl(ForwardDecl, typedefString); 11010b57cec5SDimitry Andric } 11020b57cec5SDimitry Andric RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString); 11030b57cec5SDimitry Andric } 11040b57cec5SDimitry Andric 11050b57cec5SDimitry Andric void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { 11060b57cec5SDimitry Andric // When method is a synthesized one, such as a getter/setter there is 11070b57cec5SDimitry Andric // nothing to rewrite. 11080b57cec5SDimitry Andric if (Method->isImplicit()) 11090b57cec5SDimitry Andric return; 11100b57cec5SDimitry Andric SourceLocation LocStart = Method->getBeginLoc(); 11110b57cec5SDimitry Andric SourceLocation LocEnd = Method->getEndLoc(); 11120b57cec5SDimitry Andric 11130b57cec5SDimitry Andric if (SM->getExpansionLineNumber(LocEnd) > 11140b57cec5SDimitry Andric SM->getExpansionLineNumber(LocStart)) { 11150b57cec5SDimitry Andric InsertText(LocStart, "#if 0\n"); 11160b57cec5SDimitry Andric ReplaceText(LocEnd, 1, ";\n#endif\n"); 11170b57cec5SDimitry Andric } else { 11180b57cec5SDimitry Andric InsertText(LocStart, "// "); 11190b57cec5SDimitry Andric } 11200b57cec5SDimitry Andric } 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) { 11230b57cec5SDimitry Andric SourceLocation Loc = prop->getAtLoc(); 11240b57cec5SDimitry Andric 11250b57cec5SDimitry Andric ReplaceText(Loc, 0, "// "); 11260b57cec5SDimitry Andric // FIXME: handle properties that are declared across multiple lines. 11270b57cec5SDimitry Andric } 11280b57cec5SDimitry Andric 11290b57cec5SDimitry Andric void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { 11300b57cec5SDimitry Andric SourceLocation LocStart = CatDecl->getBeginLoc(); 11310b57cec5SDimitry Andric 11320b57cec5SDimitry Andric // FIXME: handle category headers that are declared across multiple lines. 11330b57cec5SDimitry Andric if (CatDecl->getIvarRBraceLoc().isValid()) { 11340b57cec5SDimitry Andric ReplaceText(LocStart, 1, "/** "); 11350b57cec5SDimitry Andric ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ "); 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric else { 11380b57cec5SDimitry Andric ReplaceText(LocStart, 0, "// "); 11390b57cec5SDimitry Andric } 11400b57cec5SDimitry Andric 11410b57cec5SDimitry Andric for (auto *I : CatDecl->instance_properties()) 11420b57cec5SDimitry Andric RewriteProperty(I); 11430b57cec5SDimitry Andric 11440b57cec5SDimitry Andric for (auto *I : CatDecl->instance_methods()) 11450b57cec5SDimitry Andric RewriteMethodDeclaration(I); 11460b57cec5SDimitry Andric for (auto *I : CatDecl->class_methods()) 11470b57cec5SDimitry Andric RewriteMethodDeclaration(I); 11480b57cec5SDimitry Andric 11490b57cec5SDimitry Andric // Lastly, comment out the @end. 11500b57cec5SDimitry Andric ReplaceText(CatDecl->getAtEndRange().getBegin(), 11510b57cec5SDimitry Andric strlen("@end"), "/* @end */\n"); 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric 11540b57cec5SDimitry Andric void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { 11550b57cec5SDimitry Andric SourceLocation LocStart = PDecl->getBeginLoc(); 11560b57cec5SDimitry Andric assert(PDecl->isThisDeclarationADefinition()); 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric // FIXME: handle protocol headers that are declared across multiple lines. 11590b57cec5SDimitry Andric ReplaceText(LocStart, 0, "// "); 11600b57cec5SDimitry Andric 11610b57cec5SDimitry Andric for (auto *I : PDecl->instance_methods()) 11620b57cec5SDimitry Andric RewriteMethodDeclaration(I); 11630b57cec5SDimitry Andric for (auto *I : PDecl->class_methods()) 11640b57cec5SDimitry Andric RewriteMethodDeclaration(I); 11650b57cec5SDimitry Andric for (auto *I : PDecl->instance_properties()) 11660b57cec5SDimitry Andric RewriteProperty(I); 11670b57cec5SDimitry Andric 11680b57cec5SDimitry Andric // Lastly, comment out the @end. 11690b57cec5SDimitry Andric SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); 11700b57cec5SDimitry Andric ReplaceText(LocEnd, strlen("@end"), "/* @end */\n"); 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric // Must comment out @optional/@required 11730b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 11740b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 11750b57cec5SDimitry Andric for (const char *p = startBuf; p < endBuf; p++) { 11760b57cec5SDimitry Andric if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { 11770b57cec5SDimitry Andric SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 11780b57cec5SDimitry Andric ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andric } 11810b57cec5SDimitry Andric else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { 11820b57cec5SDimitry Andric SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 11830b57cec5SDimitry Andric ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric } 11860b57cec5SDimitry Andric } 11870b57cec5SDimitry Andric } 11880b57cec5SDimitry Andric 11890b57cec5SDimitry Andric void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) { 11900b57cec5SDimitry Andric SourceLocation LocStart = (*D.begin())->getBeginLoc(); 11910b57cec5SDimitry Andric if (LocStart.isInvalid()) 11920b57cec5SDimitry Andric llvm_unreachable("Invalid SourceLocation"); 11930b57cec5SDimitry Andric // FIXME: handle forward protocol that are declared across multiple lines. 11940b57cec5SDimitry Andric ReplaceText(LocStart, 0, "// "); 11950b57cec5SDimitry Andric } 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric void 11980b57cec5SDimitry Andric RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) { 11990b57cec5SDimitry Andric SourceLocation LocStart = DG[0]->getBeginLoc(); 12000b57cec5SDimitry Andric if (LocStart.isInvalid()) 12010b57cec5SDimitry Andric llvm_unreachable("Invalid SourceLocation"); 12020b57cec5SDimitry Andric // FIXME: handle forward protocol that are declared across multiple lines. 12030b57cec5SDimitry Andric ReplaceText(LocStart, 0, "// "); 12040b57cec5SDimitry Andric } 12050b57cec5SDimitry Andric 12060b57cec5SDimitry Andric void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr, 12070b57cec5SDimitry Andric const FunctionType *&FPRetType) { 12080b57cec5SDimitry Andric if (T->isObjCQualifiedIdType()) 12090b57cec5SDimitry Andric ResultStr += "id"; 12100b57cec5SDimitry Andric else if (T->isFunctionPointerType() || 12110b57cec5SDimitry Andric T->isBlockPointerType()) { 12120b57cec5SDimitry Andric // needs special handling, since pointer-to-functions have special 12130b57cec5SDimitry Andric // syntax (where a decaration models use). 12140b57cec5SDimitry Andric QualType retType = T; 12150b57cec5SDimitry Andric QualType PointeeTy; 12160b57cec5SDimitry Andric if (const PointerType* PT = retType->getAs<PointerType>()) 12170b57cec5SDimitry Andric PointeeTy = PT->getPointeeType(); 12180b57cec5SDimitry Andric else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) 12190b57cec5SDimitry Andric PointeeTy = BPT->getPointeeType(); 12200b57cec5SDimitry Andric if ((FPRetType = PointeeTy->getAs<FunctionType>())) { 12210b57cec5SDimitry Andric ResultStr += 12220b57cec5SDimitry Andric FPRetType->getReturnType().getAsString(Context->getPrintingPolicy()); 12230b57cec5SDimitry Andric ResultStr += "(*"; 12240b57cec5SDimitry Andric } 12250b57cec5SDimitry Andric } else 12260b57cec5SDimitry Andric ResultStr += T.getAsString(Context->getPrintingPolicy()); 12270b57cec5SDimitry Andric } 12280b57cec5SDimitry Andric 12290b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 12300b57cec5SDimitry Andric ObjCMethodDecl *OMD, 12310b57cec5SDimitry Andric std::string &ResultStr) { 12320b57cec5SDimitry Andric //fprintf(stderr,"In RewriteObjCMethodDecl\n"); 12330b57cec5SDimitry Andric const FunctionType *FPRetType = nullptr; 12340b57cec5SDimitry Andric ResultStr += "\nstatic "; 12350b57cec5SDimitry Andric RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType); 12360b57cec5SDimitry Andric ResultStr += " "; 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric // Unique method name 12390b57cec5SDimitry Andric std::string NameStr; 12400b57cec5SDimitry Andric 12410b57cec5SDimitry Andric if (OMD->isInstanceMethod()) 12420b57cec5SDimitry Andric NameStr += "_I_"; 12430b57cec5SDimitry Andric else 12440b57cec5SDimitry Andric NameStr += "_C_"; 12450b57cec5SDimitry Andric 12460b57cec5SDimitry Andric NameStr += IDecl->getNameAsString(); 12470b57cec5SDimitry Andric NameStr += "_"; 12480b57cec5SDimitry Andric 12490b57cec5SDimitry Andric if (ObjCCategoryImplDecl *CID = 12500b57cec5SDimitry Andric dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 12510b57cec5SDimitry Andric NameStr += CID->getNameAsString(); 12520b57cec5SDimitry Andric NameStr += "_"; 12530b57cec5SDimitry Andric } 12540b57cec5SDimitry Andric // Append selector names, replacing ':' with '_' 12550b57cec5SDimitry Andric { 12560b57cec5SDimitry Andric std::string selString = OMD->getSelector().getAsString(); 12570b57cec5SDimitry Andric int len = selString.size(); 12580b57cec5SDimitry Andric for (int i = 0; i < len; i++) 12590b57cec5SDimitry Andric if (selString[i] == ':') 12600b57cec5SDimitry Andric selString[i] = '_'; 12610b57cec5SDimitry Andric NameStr += selString; 12620b57cec5SDimitry Andric } 12630b57cec5SDimitry Andric // Remember this name for metadata emission 12640b57cec5SDimitry Andric MethodInternalNames[OMD] = NameStr; 12650b57cec5SDimitry Andric ResultStr += NameStr; 12660b57cec5SDimitry Andric 12670b57cec5SDimitry Andric // Rewrite arguments 12680b57cec5SDimitry Andric ResultStr += "("; 12690b57cec5SDimitry Andric 12700b57cec5SDimitry Andric // invisible arguments 12710b57cec5SDimitry Andric if (OMD->isInstanceMethod()) { 12720b57cec5SDimitry Andric QualType selfTy = Context->getObjCInterfaceType(IDecl); 12730b57cec5SDimitry Andric selfTy = Context->getPointerType(selfTy); 12740b57cec5SDimitry Andric if (!LangOpts.MicrosoftExt) { 12750b57cec5SDimitry Andric if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl))) 12760b57cec5SDimitry Andric ResultStr += "struct "; 12770b57cec5SDimitry Andric } 12780b57cec5SDimitry Andric // When rewriting for Microsoft, explicitly omit the structure name. 12790b57cec5SDimitry Andric ResultStr += IDecl->getNameAsString(); 12800b57cec5SDimitry Andric ResultStr += " *"; 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric else 12830b57cec5SDimitry Andric ResultStr += Context->getObjCClassType().getAsString( 12840b57cec5SDimitry Andric Context->getPrintingPolicy()); 12850b57cec5SDimitry Andric 12860b57cec5SDimitry Andric ResultStr += " self, "; 12870b57cec5SDimitry Andric ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy()); 12880b57cec5SDimitry Andric ResultStr += " _cmd"; 12890b57cec5SDimitry Andric 12900b57cec5SDimitry Andric // Method arguments. 12910b57cec5SDimitry Andric for (const auto *PDecl : OMD->parameters()) { 12920b57cec5SDimitry Andric ResultStr += ", "; 12930b57cec5SDimitry Andric if (PDecl->getType()->isObjCQualifiedIdType()) { 12940b57cec5SDimitry Andric ResultStr += "id "; 12950b57cec5SDimitry Andric ResultStr += PDecl->getNameAsString(); 12960b57cec5SDimitry Andric } else { 12970b57cec5SDimitry Andric std::string Name = PDecl->getNameAsString(); 12980b57cec5SDimitry Andric QualType QT = PDecl->getType(); 12990b57cec5SDimitry Andric // Make sure we convert "t (^)(...)" to "t (*)(...)". 13000b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(QT); 13010b57cec5SDimitry Andric QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 13020b57cec5SDimitry Andric ResultStr += Name; 13030b57cec5SDimitry Andric } 13040b57cec5SDimitry Andric } 13050b57cec5SDimitry Andric if (OMD->isVariadic()) 13060b57cec5SDimitry Andric ResultStr += ", ..."; 13070b57cec5SDimitry Andric ResultStr += ") "; 13080b57cec5SDimitry Andric 13090b57cec5SDimitry Andric if (FPRetType) { 13100b57cec5SDimitry Andric ResultStr += ")"; // close the precedence "scope" for "*". 13110b57cec5SDimitry Andric 13120b57cec5SDimitry Andric // Now, emit the argument types (if any). 13130b57cec5SDimitry Andric if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { 13140b57cec5SDimitry Andric ResultStr += "("; 13150b57cec5SDimitry Andric for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) { 13160b57cec5SDimitry Andric if (i) ResultStr += ", "; 13170b57cec5SDimitry Andric std::string ParamStr = 13180b57cec5SDimitry Andric FT->getParamType(i).getAsString(Context->getPrintingPolicy()); 13190b57cec5SDimitry Andric ResultStr += ParamStr; 13200b57cec5SDimitry Andric } 13210b57cec5SDimitry Andric if (FT->isVariadic()) { 13220b57cec5SDimitry Andric if (FT->getNumParams()) 13230b57cec5SDimitry Andric ResultStr += ", "; 13240b57cec5SDimitry Andric ResultStr += "..."; 13250b57cec5SDimitry Andric } 13260b57cec5SDimitry Andric ResultStr += ")"; 13270b57cec5SDimitry Andric } else { 13280b57cec5SDimitry Andric ResultStr += "()"; 13290b57cec5SDimitry Andric } 13300b57cec5SDimitry Andric } 13310b57cec5SDimitry Andric } 13320b57cec5SDimitry Andric 13330b57cec5SDimitry Andric void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) { 13340b57cec5SDimitry Andric ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); 13350b57cec5SDimitry Andric ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); 1336a7dea167SDimitry Andric assert((IMD || CID) && "Unknown implementation type"); 13370b57cec5SDimitry Andric 13380b57cec5SDimitry Andric if (IMD) { 13390b57cec5SDimitry Andric if (IMD->getIvarRBraceLoc().isValid()) { 13400b57cec5SDimitry Andric ReplaceText(IMD->getBeginLoc(), 1, "/** "); 13410b57cec5SDimitry Andric ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ "); 13420b57cec5SDimitry Andric } 13430b57cec5SDimitry Andric else { 13440b57cec5SDimitry Andric InsertText(IMD->getBeginLoc(), "// "); 13450b57cec5SDimitry Andric } 13460b57cec5SDimitry Andric } 13470b57cec5SDimitry Andric else 13480b57cec5SDimitry Andric InsertText(CID->getBeginLoc(), "// "); 13490b57cec5SDimitry Andric 13500b57cec5SDimitry Andric for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) { 1351480093f4SDimitry Andric if (!OMD->getBody()) 1352480093f4SDimitry Andric continue; 13530b57cec5SDimitry Andric std::string ResultStr; 13540b57cec5SDimitry Andric RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 13550b57cec5SDimitry Andric SourceLocation LocStart = OMD->getBeginLoc(); 13560b57cec5SDimitry Andric SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc(); 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 13590b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 13600b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf, ResultStr); 13610b57cec5SDimitry Andric } 13620b57cec5SDimitry Andric 13630b57cec5SDimitry Andric for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) { 1364480093f4SDimitry Andric if (!OMD->getBody()) 1365480093f4SDimitry Andric continue; 13660b57cec5SDimitry Andric std::string ResultStr; 13670b57cec5SDimitry Andric RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 13680b57cec5SDimitry Andric SourceLocation LocStart = OMD->getBeginLoc(); 13690b57cec5SDimitry Andric SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc(); 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 13720b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 13730b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf, ResultStr); 13740b57cec5SDimitry Andric } 13750b57cec5SDimitry Andric for (auto *I : IMD ? IMD->property_impls() : CID->property_impls()) 13760b57cec5SDimitry Andric RewritePropertyImplDecl(I, IMD, CID); 13770b57cec5SDimitry Andric 13780b57cec5SDimitry Andric InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// "); 13790b57cec5SDimitry Andric } 13800b57cec5SDimitry Andric 13810b57cec5SDimitry Andric void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 13820b57cec5SDimitry Andric // Do not synthesize more than once. 13830b57cec5SDimitry Andric if (ObjCSynthesizedStructs.count(ClassDecl)) 13840b57cec5SDimitry Andric return; 13850b57cec5SDimitry Andric // Make sure super class's are written before current class is written. 13860b57cec5SDimitry Andric ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass(); 13870b57cec5SDimitry Andric while (SuperClass) { 13880b57cec5SDimitry Andric RewriteInterfaceDecl(SuperClass); 13890b57cec5SDimitry Andric SuperClass = SuperClass->getSuperClass(); 13900b57cec5SDimitry Andric } 13910b57cec5SDimitry Andric std::string ResultStr; 13920b57cec5SDimitry Andric if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) { 13930b57cec5SDimitry Andric // we haven't seen a forward decl - generate a typedef. 13940b57cec5SDimitry Andric RewriteOneForwardClassDecl(ClassDecl, ResultStr); 13950b57cec5SDimitry Andric RewriteIvarOffsetSymbols(ClassDecl, ResultStr); 13960b57cec5SDimitry Andric 13970b57cec5SDimitry Andric RewriteObjCInternalStruct(ClassDecl, ResultStr); 13980b57cec5SDimitry Andric // Mark this typedef as having been written into its c++ equivalent. 13990b57cec5SDimitry Andric ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl()); 14000b57cec5SDimitry Andric 14010b57cec5SDimitry Andric for (auto *I : ClassDecl->instance_properties()) 14020b57cec5SDimitry Andric RewriteProperty(I); 14030b57cec5SDimitry Andric for (auto *I : ClassDecl->instance_methods()) 14040b57cec5SDimitry Andric RewriteMethodDeclaration(I); 14050b57cec5SDimitry Andric for (auto *I : ClassDecl->class_methods()) 14060b57cec5SDimitry Andric RewriteMethodDeclaration(I); 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric // Lastly, comment out the @end. 14090b57cec5SDimitry Andric ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), 14100b57cec5SDimitry Andric "/* @end */\n"); 14110b57cec5SDimitry Andric } 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) { 14150b57cec5SDimitry Andric SourceRange OldRange = PseudoOp->getSourceRange(); 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric // We just magically know some things about the structure of this 14180b57cec5SDimitry Andric // expression. 14190b57cec5SDimitry Andric ObjCMessageExpr *OldMsg = 14200b57cec5SDimitry Andric cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr( 14210b57cec5SDimitry Andric PseudoOp->getNumSemanticExprs() - 1)); 14220b57cec5SDimitry Andric 14230b57cec5SDimitry Andric // Because the rewriter doesn't allow us to rewrite rewritten code, 14240b57cec5SDimitry Andric // we need to suppress rewriting the sub-statements. 14250b57cec5SDimitry Andric Expr *Base; 14260b57cec5SDimitry Andric SmallVector<Expr*, 2> Args; 14270b57cec5SDimitry Andric { 14280b57cec5SDimitry Andric DisableReplaceStmtScope S(*this); 14290b57cec5SDimitry Andric 14300b57cec5SDimitry Andric // Rebuild the base expression if we have one. 14310b57cec5SDimitry Andric Base = nullptr; 14320b57cec5SDimitry Andric if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 14330b57cec5SDimitry Andric Base = OldMsg->getInstanceReceiver(); 14340b57cec5SDimitry Andric Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 14350b57cec5SDimitry Andric Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 14360b57cec5SDimitry Andric } 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric unsigned numArgs = OldMsg->getNumArgs(); 14390b57cec5SDimitry Andric for (unsigned i = 0; i < numArgs; i++) { 14400b57cec5SDimitry Andric Expr *Arg = OldMsg->getArg(i); 14410b57cec5SDimitry Andric if (isa<OpaqueValueExpr>(Arg)) 14420b57cec5SDimitry Andric Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr(); 14430b57cec5SDimitry Andric Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg)); 14440b57cec5SDimitry Andric Args.push_back(Arg); 14450b57cec5SDimitry Andric } 14460b57cec5SDimitry Andric } 14470b57cec5SDimitry Andric 14480b57cec5SDimitry Andric // TODO: avoid this copy. 14490b57cec5SDimitry Andric SmallVector<SourceLocation, 1> SelLocs; 14500b57cec5SDimitry Andric OldMsg->getSelectorLocs(SelLocs); 14510b57cec5SDimitry Andric 14520b57cec5SDimitry Andric ObjCMessageExpr *NewMsg = nullptr; 14530b57cec5SDimitry Andric switch (OldMsg->getReceiverKind()) { 14540b57cec5SDimitry Andric case ObjCMessageExpr::Class: 14550b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 14560b57cec5SDimitry Andric OldMsg->getValueKind(), 14570b57cec5SDimitry Andric OldMsg->getLeftLoc(), 14580b57cec5SDimitry Andric OldMsg->getClassReceiverTypeInfo(), 14590b57cec5SDimitry Andric OldMsg->getSelector(), 14600b57cec5SDimitry Andric SelLocs, 14610b57cec5SDimitry Andric OldMsg->getMethodDecl(), 14620b57cec5SDimitry Andric Args, 14630b57cec5SDimitry Andric OldMsg->getRightLoc(), 14640b57cec5SDimitry Andric OldMsg->isImplicit()); 14650b57cec5SDimitry Andric break; 14660b57cec5SDimitry Andric 14670b57cec5SDimitry Andric case ObjCMessageExpr::Instance: 14680b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 14690b57cec5SDimitry Andric OldMsg->getValueKind(), 14700b57cec5SDimitry Andric OldMsg->getLeftLoc(), 14710b57cec5SDimitry Andric Base, 14720b57cec5SDimitry Andric OldMsg->getSelector(), 14730b57cec5SDimitry Andric SelLocs, 14740b57cec5SDimitry Andric OldMsg->getMethodDecl(), 14750b57cec5SDimitry Andric Args, 14760b57cec5SDimitry Andric OldMsg->getRightLoc(), 14770b57cec5SDimitry Andric OldMsg->isImplicit()); 14780b57cec5SDimitry Andric break; 14790b57cec5SDimitry Andric 14800b57cec5SDimitry Andric case ObjCMessageExpr::SuperClass: 14810b57cec5SDimitry Andric case ObjCMessageExpr::SuperInstance: 14820b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 14830b57cec5SDimitry Andric OldMsg->getValueKind(), 14840b57cec5SDimitry Andric OldMsg->getLeftLoc(), 14850b57cec5SDimitry Andric OldMsg->getSuperLoc(), 14860b57cec5SDimitry Andric OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 14870b57cec5SDimitry Andric OldMsg->getSuperType(), 14880b57cec5SDimitry Andric OldMsg->getSelector(), 14890b57cec5SDimitry Andric SelLocs, 14900b57cec5SDimitry Andric OldMsg->getMethodDecl(), 14910b57cec5SDimitry Andric Args, 14920b57cec5SDimitry Andric OldMsg->getRightLoc(), 14930b57cec5SDimitry Andric OldMsg->isImplicit()); 14940b57cec5SDimitry Andric break; 14950b57cec5SDimitry Andric } 14960b57cec5SDimitry Andric 14970b57cec5SDimitry Andric Stmt *Replacement = SynthMessageExpr(NewMsg); 14980b57cec5SDimitry Andric ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 14990b57cec5SDimitry Andric return Replacement; 15000b57cec5SDimitry Andric } 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) { 15030b57cec5SDimitry Andric SourceRange OldRange = PseudoOp->getSourceRange(); 15040b57cec5SDimitry Andric 15050b57cec5SDimitry Andric // We just magically know some things about the structure of this 15060b57cec5SDimitry Andric // expression. 15070b57cec5SDimitry Andric ObjCMessageExpr *OldMsg = 15080b57cec5SDimitry Andric cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit()); 15090b57cec5SDimitry Andric 15100b57cec5SDimitry Andric // Because the rewriter doesn't allow us to rewrite rewritten code, 15110b57cec5SDimitry Andric // we need to suppress rewriting the sub-statements. 15120b57cec5SDimitry Andric Expr *Base = nullptr; 15130b57cec5SDimitry Andric SmallVector<Expr*, 1> Args; 15140b57cec5SDimitry Andric { 15150b57cec5SDimitry Andric DisableReplaceStmtScope S(*this); 15160b57cec5SDimitry Andric // Rebuild the base expression if we have one. 15170b57cec5SDimitry Andric if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 15180b57cec5SDimitry Andric Base = OldMsg->getInstanceReceiver(); 15190b57cec5SDimitry Andric Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 15200b57cec5SDimitry Andric Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric unsigned numArgs = OldMsg->getNumArgs(); 15230b57cec5SDimitry Andric for (unsigned i = 0; i < numArgs; i++) { 15240b57cec5SDimitry Andric Expr *Arg = OldMsg->getArg(i); 15250b57cec5SDimitry Andric if (isa<OpaqueValueExpr>(Arg)) 15260b57cec5SDimitry Andric Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr(); 15270b57cec5SDimitry Andric Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg)); 15280b57cec5SDimitry Andric Args.push_back(Arg); 15290b57cec5SDimitry Andric } 15300b57cec5SDimitry Andric } 15310b57cec5SDimitry Andric 15320b57cec5SDimitry Andric // Intentionally empty. 15330b57cec5SDimitry Andric SmallVector<SourceLocation, 1> SelLocs; 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric ObjCMessageExpr *NewMsg = nullptr; 15360b57cec5SDimitry Andric switch (OldMsg->getReceiverKind()) { 15370b57cec5SDimitry Andric case ObjCMessageExpr::Class: 15380b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 15390b57cec5SDimitry Andric OldMsg->getValueKind(), 15400b57cec5SDimitry Andric OldMsg->getLeftLoc(), 15410b57cec5SDimitry Andric OldMsg->getClassReceiverTypeInfo(), 15420b57cec5SDimitry Andric OldMsg->getSelector(), 15430b57cec5SDimitry Andric SelLocs, 15440b57cec5SDimitry Andric OldMsg->getMethodDecl(), 15450b57cec5SDimitry Andric Args, 15460b57cec5SDimitry Andric OldMsg->getRightLoc(), 15470b57cec5SDimitry Andric OldMsg->isImplicit()); 15480b57cec5SDimitry Andric break; 15490b57cec5SDimitry Andric 15500b57cec5SDimitry Andric case ObjCMessageExpr::Instance: 15510b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 15520b57cec5SDimitry Andric OldMsg->getValueKind(), 15530b57cec5SDimitry Andric OldMsg->getLeftLoc(), 15540b57cec5SDimitry Andric Base, 15550b57cec5SDimitry Andric OldMsg->getSelector(), 15560b57cec5SDimitry Andric SelLocs, 15570b57cec5SDimitry Andric OldMsg->getMethodDecl(), 15580b57cec5SDimitry Andric Args, 15590b57cec5SDimitry Andric OldMsg->getRightLoc(), 15600b57cec5SDimitry Andric OldMsg->isImplicit()); 15610b57cec5SDimitry Andric break; 15620b57cec5SDimitry Andric 15630b57cec5SDimitry Andric case ObjCMessageExpr::SuperClass: 15640b57cec5SDimitry Andric case ObjCMessageExpr::SuperInstance: 15650b57cec5SDimitry Andric NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 15660b57cec5SDimitry Andric OldMsg->getValueKind(), 15670b57cec5SDimitry Andric OldMsg->getLeftLoc(), 15680b57cec5SDimitry Andric OldMsg->getSuperLoc(), 15690b57cec5SDimitry Andric OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 15700b57cec5SDimitry Andric OldMsg->getSuperType(), 15710b57cec5SDimitry Andric OldMsg->getSelector(), 15720b57cec5SDimitry Andric SelLocs, 15730b57cec5SDimitry Andric OldMsg->getMethodDecl(), 15740b57cec5SDimitry Andric Args, 15750b57cec5SDimitry Andric OldMsg->getRightLoc(), 15760b57cec5SDimitry Andric OldMsg->isImplicit()); 15770b57cec5SDimitry Andric break; 15780b57cec5SDimitry Andric } 15790b57cec5SDimitry Andric 15800b57cec5SDimitry Andric Stmt *Replacement = SynthMessageExpr(NewMsg); 15810b57cec5SDimitry Andric ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 15820b57cec5SDimitry Andric return Replacement; 15830b57cec5SDimitry Andric } 15840b57cec5SDimitry Andric 15850b57cec5SDimitry Andric /// SynthCountByEnumWithState - To print: 15860b57cec5SDimitry Andric /// ((NSUInteger (*) 15870b57cec5SDimitry Andric /// (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger)) 15880b57cec5SDimitry Andric /// (void *)objc_msgSend)((id)l_collection, 15890b57cec5SDimitry Andric /// sel_registerName( 15900b57cec5SDimitry Andric /// "countByEnumeratingWithState:objects:count:"), 15910b57cec5SDimitry Andric /// &enumState, 15920b57cec5SDimitry Andric /// (id *)__rw_items, (NSUInteger)16) 15930b57cec5SDimitry Andric /// 15940b57cec5SDimitry Andric void RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) { 15950b57cec5SDimitry Andric buf += "((_WIN_NSUInteger (*) (id, SEL, struct __objcFastEnumerationState *, " 15960b57cec5SDimitry Andric "id *, _WIN_NSUInteger))(void *)objc_msgSend)"; 15970b57cec5SDimitry Andric buf += "\n\t\t"; 15980b57cec5SDimitry Andric buf += "((id)l_collection,\n\t\t"; 15990b57cec5SDimitry Andric buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; 16000b57cec5SDimitry Andric buf += "\n\t\t"; 16010b57cec5SDimitry Andric buf += "&enumState, " 16020b57cec5SDimitry Andric "(id *)__rw_items, (_WIN_NSUInteger)16)"; 16030b57cec5SDimitry Andric } 16040b57cec5SDimitry Andric 16050b57cec5SDimitry Andric /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach 16060b57cec5SDimitry Andric /// statement to exit to its outer synthesized loop. 16070b57cec5SDimitry Andric /// 16080b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) { 16090b57cec5SDimitry Andric if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 16100b57cec5SDimitry Andric return S; 16110b57cec5SDimitry Andric // replace break with goto __break_label 16120b57cec5SDimitry Andric std::string buf; 16130b57cec5SDimitry Andric 16140b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 16150b57cec5SDimitry Andric buf = "goto __break_label_"; 16160b57cec5SDimitry Andric buf += utostr(ObjCBcLabelNo.back()); 16170b57cec5SDimitry Andric ReplaceText(startLoc, strlen("break"), buf); 16180b57cec5SDimitry Andric 16190b57cec5SDimitry Andric return nullptr; 16200b57cec5SDimitry Andric } 16210b57cec5SDimitry Andric 16220b57cec5SDimitry Andric void RewriteModernObjC::ConvertSourceLocationToLineDirective( 16230b57cec5SDimitry Andric SourceLocation Loc, 16240b57cec5SDimitry Andric std::string &LineString) { 16250b57cec5SDimitry Andric if (Loc.isFileID() && GenerateLineInfo) { 16260b57cec5SDimitry Andric LineString += "\n#line "; 16270b57cec5SDimitry Andric PresumedLoc PLoc = SM->getPresumedLoc(Loc); 16280b57cec5SDimitry Andric LineString += utostr(PLoc.getLine()); 16290b57cec5SDimitry Andric LineString += " \""; 16300b57cec5SDimitry Andric LineString += Lexer::Stringify(PLoc.getFilename()); 16310b57cec5SDimitry Andric LineString += "\"\n"; 16320b57cec5SDimitry Andric } 16330b57cec5SDimitry Andric } 16340b57cec5SDimitry Andric 16350b57cec5SDimitry Andric /// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach 16360b57cec5SDimitry Andric /// statement to continue with its inner synthesized loop. 16370b57cec5SDimitry Andric /// 16380b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) { 16390b57cec5SDimitry Andric if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 16400b57cec5SDimitry Andric return S; 16410b57cec5SDimitry Andric // replace continue with goto __continue_label 16420b57cec5SDimitry Andric std::string buf; 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 16450b57cec5SDimitry Andric buf = "goto __continue_label_"; 16460b57cec5SDimitry Andric buf += utostr(ObjCBcLabelNo.back()); 16470b57cec5SDimitry Andric ReplaceText(startLoc, strlen("continue"), buf); 16480b57cec5SDimitry Andric 16490b57cec5SDimitry Andric return nullptr; 16500b57cec5SDimitry Andric } 16510b57cec5SDimitry Andric 16520b57cec5SDimitry Andric /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. 16530b57cec5SDimitry Andric /// It rewrites: 16540b57cec5SDimitry Andric /// for ( type elem in collection) { stmts; } 16550b57cec5SDimitry Andric 16560b57cec5SDimitry Andric /// Into: 16570b57cec5SDimitry Andric /// { 16580b57cec5SDimitry Andric /// type elem; 16590b57cec5SDimitry Andric /// struct __objcFastEnumerationState enumState = { 0 }; 16600b57cec5SDimitry Andric /// id __rw_items[16]; 16610b57cec5SDimitry Andric /// id l_collection = (id)collection; 16620b57cec5SDimitry Andric /// NSUInteger limit = [l_collection countByEnumeratingWithState:&enumState 16630b57cec5SDimitry Andric /// objects:__rw_items count:16]; 16640b57cec5SDimitry Andric /// if (limit) { 16650b57cec5SDimitry Andric /// unsigned long startMutations = *enumState.mutationsPtr; 16660b57cec5SDimitry Andric /// do { 16670b57cec5SDimitry Andric /// unsigned long counter = 0; 16680b57cec5SDimitry Andric /// do { 16690b57cec5SDimitry Andric /// if (startMutations != *enumState.mutationsPtr) 16700b57cec5SDimitry Andric /// objc_enumerationMutation(l_collection); 16710b57cec5SDimitry Andric /// elem = (type)enumState.itemsPtr[counter++]; 16720b57cec5SDimitry Andric /// stmts; 16730b57cec5SDimitry Andric /// __continue_label: ; 16740b57cec5SDimitry Andric /// } while (counter < limit); 16750b57cec5SDimitry Andric /// } while ((limit = [l_collection countByEnumeratingWithState:&enumState 16760b57cec5SDimitry Andric /// objects:__rw_items count:16])); 16770b57cec5SDimitry Andric /// elem = nil; 16780b57cec5SDimitry Andric /// __break_label: ; 16790b57cec5SDimitry Andric /// } 16800b57cec5SDimitry Andric /// else 16810b57cec5SDimitry Andric /// elem = nil; 16820b57cec5SDimitry Andric /// } 16830b57cec5SDimitry Andric /// 16840b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 16850b57cec5SDimitry Andric SourceLocation OrigEnd) { 16860b57cec5SDimitry Andric assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); 16870b57cec5SDimitry Andric assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 16880b57cec5SDimitry Andric "ObjCForCollectionStmt Statement stack mismatch"); 16890b57cec5SDimitry Andric assert(!ObjCBcLabelNo.empty() && 16900b57cec5SDimitry Andric "ObjCForCollectionStmt - Label No stack empty"); 16910b57cec5SDimitry Andric 16920b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 16930b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 16940b57cec5SDimitry Andric StringRef elementName; 16950b57cec5SDimitry Andric std::string elementTypeAsString; 16960b57cec5SDimitry Andric std::string buf; 16970b57cec5SDimitry Andric // line directive first. 16980b57cec5SDimitry Andric SourceLocation ForEachLoc = S->getForLoc(); 16990b57cec5SDimitry Andric ConvertSourceLocationToLineDirective(ForEachLoc, buf); 17000b57cec5SDimitry Andric buf += "{\n\t"; 17010b57cec5SDimitry Andric if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) { 17020b57cec5SDimitry Andric // type elem; 17030b57cec5SDimitry Andric NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl()); 17040b57cec5SDimitry Andric QualType ElementType = cast<ValueDecl>(D)->getType(); 17050b57cec5SDimitry Andric if (ElementType->isObjCQualifiedIdType() || 17060b57cec5SDimitry Andric ElementType->isObjCQualifiedInterfaceType()) 17070b57cec5SDimitry Andric // Simply use 'id' for all qualified types. 17080b57cec5SDimitry Andric elementTypeAsString = "id"; 17090b57cec5SDimitry Andric else 17100b57cec5SDimitry Andric elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy()); 17110b57cec5SDimitry Andric buf += elementTypeAsString; 17120b57cec5SDimitry Andric buf += " "; 17130b57cec5SDimitry Andric elementName = D->getName(); 17140b57cec5SDimitry Andric buf += elementName; 17150b57cec5SDimitry Andric buf += ";\n\t"; 17160b57cec5SDimitry Andric } 17170b57cec5SDimitry Andric else { 17180b57cec5SDimitry Andric DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); 17190b57cec5SDimitry Andric elementName = DR->getDecl()->getName(); 17200b57cec5SDimitry Andric ValueDecl *VD = DR->getDecl(); 17210b57cec5SDimitry Andric if (VD->getType()->isObjCQualifiedIdType() || 17220b57cec5SDimitry Andric VD->getType()->isObjCQualifiedInterfaceType()) 17230b57cec5SDimitry Andric // Simply use 'id' for all qualified types. 17240b57cec5SDimitry Andric elementTypeAsString = "id"; 17250b57cec5SDimitry Andric else 17260b57cec5SDimitry Andric elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy()); 17270b57cec5SDimitry Andric } 17280b57cec5SDimitry Andric 17290b57cec5SDimitry Andric // struct __objcFastEnumerationState enumState = { 0 }; 17300b57cec5SDimitry Andric buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; 17310b57cec5SDimitry Andric // id __rw_items[16]; 17320b57cec5SDimitry Andric buf += "id __rw_items[16];\n\t"; 17330b57cec5SDimitry Andric // id l_collection = (id) 17340b57cec5SDimitry Andric buf += "id l_collection = (id)"; 17350b57cec5SDimitry Andric // Find start location of 'collection' the hard way! 17360b57cec5SDimitry Andric const char *startCollectionBuf = startBuf; 17370b57cec5SDimitry Andric startCollectionBuf += 3; // skip 'for' 17380b57cec5SDimitry Andric startCollectionBuf = strchr(startCollectionBuf, '('); 17390b57cec5SDimitry Andric startCollectionBuf++; // skip '(' 17400b57cec5SDimitry Andric // find 'in' and skip it. 17410b57cec5SDimitry Andric while (*startCollectionBuf != ' ' || 17420b57cec5SDimitry Andric *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' || 17430b57cec5SDimitry Andric (*(startCollectionBuf+3) != ' ' && 17440b57cec5SDimitry Andric *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) 17450b57cec5SDimitry Andric startCollectionBuf++; 17460b57cec5SDimitry Andric startCollectionBuf += 3; 17470b57cec5SDimitry Andric 17480b57cec5SDimitry Andric // Replace: "for (type element in" with string constructed thus far. 17490b57cec5SDimitry Andric ReplaceText(startLoc, startCollectionBuf - startBuf, buf); 17500b57cec5SDimitry Andric // Replace ')' in for '(' type elem in collection ')' with ';' 17510b57cec5SDimitry Andric SourceLocation rightParenLoc = S->getRParenLoc(); 17520b57cec5SDimitry Andric const char *rparenBuf = SM->getCharacterData(rightParenLoc); 17530b57cec5SDimitry Andric SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf); 17540b57cec5SDimitry Andric buf = ";\n\t"; 17550b57cec5SDimitry Andric 17560b57cec5SDimitry Andric // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 17570b57cec5SDimitry Andric // objects:__rw_items count:16]; 17580b57cec5SDimitry Andric // which is synthesized into: 17590b57cec5SDimitry Andric // NSUInteger limit = 17600b57cec5SDimitry Andric // ((NSUInteger (*) 17610b57cec5SDimitry Andric // (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger)) 17620b57cec5SDimitry Andric // (void *)objc_msgSend)((id)l_collection, 17630b57cec5SDimitry Andric // sel_registerName( 17640b57cec5SDimitry Andric // "countByEnumeratingWithState:objects:count:"), 17650b57cec5SDimitry Andric // (struct __objcFastEnumerationState *)&state, 17660b57cec5SDimitry Andric // (id *)__rw_items, (NSUInteger)16); 17670b57cec5SDimitry Andric buf += "_WIN_NSUInteger limit =\n\t\t"; 17680b57cec5SDimitry Andric SynthCountByEnumWithState(buf); 17690b57cec5SDimitry Andric buf += ";\n\t"; 17700b57cec5SDimitry Andric /// if (limit) { 17710b57cec5SDimitry Andric /// unsigned long startMutations = *enumState.mutationsPtr; 17720b57cec5SDimitry Andric /// do { 17730b57cec5SDimitry Andric /// unsigned long counter = 0; 17740b57cec5SDimitry Andric /// do { 17750b57cec5SDimitry Andric /// if (startMutations != *enumState.mutationsPtr) 17760b57cec5SDimitry Andric /// objc_enumerationMutation(l_collection); 17770b57cec5SDimitry Andric /// elem = (type)enumState.itemsPtr[counter++]; 17780b57cec5SDimitry Andric buf += "if (limit) {\n\t"; 17790b57cec5SDimitry Andric buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t"; 17800b57cec5SDimitry Andric buf += "do {\n\t\t"; 17810b57cec5SDimitry Andric buf += "unsigned long counter = 0;\n\t\t"; 17820b57cec5SDimitry Andric buf += "do {\n\t\t\t"; 17830b57cec5SDimitry Andric buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t"; 17840b57cec5SDimitry Andric buf += "objc_enumerationMutation(l_collection);\n\t\t\t"; 17850b57cec5SDimitry Andric buf += elementName; 17860b57cec5SDimitry Andric buf += " = ("; 17870b57cec5SDimitry Andric buf += elementTypeAsString; 17880b57cec5SDimitry Andric buf += ")enumState.itemsPtr[counter++];"; 17890b57cec5SDimitry Andric // Replace ')' in for '(' type elem in collection ')' with all of these. 17900b57cec5SDimitry Andric ReplaceText(lparenLoc, 1, buf); 17910b57cec5SDimitry Andric 17920b57cec5SDimitry Andric /// __continue_label: ; 17930b57cec5SDimitry Andric /// } while (counter < limit); 17940b57cec5SDimitry Andric /// } while ((limit = [l_collection countByEnumeratingWithState:&enumState 17950b57cec5SDimitry Andric /// objects:__rw_items count:16])); 17960b57cec5SDimitry Andric /// elem = nil; 17970b57cec5SDimitry Andric /// __break_label: ; 17980b57cec5SDimitry Andric /// } 17990b57cec5SDimitry Andric /// else 18000b57cec5SDimitry Andric /// elem = nil; 18010b57cec5SDimitry Andric /// } 18020b57cec5SDimitry Andric /// 18030b57cec5SDimitry Andric buf = ";\n\t"; 18040b57cec5SDimitry Andric buf += "__continue_label_"; 18050b57cec5SDimitry Andric buf += utostr(ObjCBcLabelNo.back()); 18060b57cec5SDimitry Andric buf += ": ;"; 18070b57cec5SDimitry Andric buf += "\n\t\t"; 18080b57cec5SDimitry Andric buf += "} while (counter < limit);\n\t"; 18090b57cec5SDimitry Andric buf += "} while ((limit = "; 18100b57cec5SDimitry Andric SynthCountByEnumWithState(buf); 18110b57cec5SDimitry Andric buf += "));\n\t"; 18120b57cec5SDimitry Andric buf += elementName; 18130b57cec5SDimitry Andric buf += " = (("; 18140b57cec5SDimitry Andric buf += elementTypeAsString; 18150b57cec5SDimitry Andric buf += ")0);\n\t"; 18160b57cec5SDimitry Andric buf += "__break_label_"; 18170b57cec5SDimitry Andric buf += utostr(ObjCBcLabelNo.back()); 18180b57cec5SDimitry Andric buf += ": ;\n\t"; 18190b57cec5SDimitry Andric buf += "}\n\t"; 18200b57cec5SDimitry Andric buf += "else\n\t\t"; 18210b57cec5SDimitry Andric buf += elementName; 18220b57cec5SDimitry Andric buf += " = (("; 18230b57cec5SDimitry Andric buf += elementTypeAsString; 18240b57cec5SDimitry Andric buf += ")0);\n\t"; 18250b57cec5SDimitry Andric buf += "}\n"; 18260b57cec5SDimitry Andric 18270b57cec5SDimitry Andric // Insert all these *after* the statement body. 18280b57cec5SDimitry Andric // FIXME: If this should support Obj-C++, support CXXTryStmt 18290b57cec5SDimitry Andric if (isa<CompoundStmt>(S->getBody())) { 18300b57cec5SDimitry Andric SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1); 18310b57cec5SDimitry Andric InsertText(endBodyLoc, buf); 18320b57cec5SDimitry Andric } else { 18330b57cec5SDimitry Andric /* Need to treat single statements specially. For example: 18340b57cec5SDimitry Andric * 18350b57cec5SDimitry Andric * for (A *a in b) if (stuff()) break; 18360b57cec5SDimitry Andric * for (A *a in b) xxxyy; 18370b57cec5SDimitry Andric * 18380b57cec5SDimitry Andric * The following code simply scans ahead to the semi to find the actual end. 18390b57cec5SDimitry Andric */ 18400b57cec5SDimitry Andric const char *stmtBuf = SM->getCharacterData(OrigEnd); 18410b57cec5SDimitry Andric const char *semiBuf = strchr(stmtBuf, ';'); 18420b57cec5SDimitry Andric assert(semiBuf && "Can't find ';'"); 18430b57cec5SDimitry Andric SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1); 18440b57cec5SDimitry Andric InsertText(endBodyLoc, buf); 18450b57cec5SDimitry Andric } 18460b57cec5SDimitry Andric Stmts.pop_back(); 18470b57cec5SDimitry Andric ObjCBcLabelNo.pop_back(); 18480b57cec5SDimitry Andric return nullptr; 18490b57cec5SDimitry Andric } 18500b57cec5SDimitry Andric 18510b57cec5SDimitry Andric static void Write_RethrowObject(std::string &buf) { 18520b57cec5SDimitry Andric buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n"; 18530b57cec5SDimitry Andric buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n"; 18540b57cec5SDimitry Andric buf += "\tid rethrow;\n"; 18550b57cec5SDimitry Andric buf += "\t} _fin_force_rethow(_rethrow);"; 18560b57cec5SDimitry Andric } 18570b57cec5SDimitry Andric 18580b57cec5SDimitry Andric /// RewriteObjCSynchronizedStmt - 18590b57cec5SDimitry Andric /// This routine rewrites @synchronized(expr) stmt; 18600b57cec5SDimitry Andric /// into: 18610b57cec5SDimitry Andric /// objc_sync_enter(expr); 18620b57cec5SDimitry Andric /// @try stmt @finally { objc_sync_exit(expr); } 18630b57cec5SDimitry Andric /// 18640b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 18650b57cec5SDimitry Andric // Get the start location and compute the semi location. 18660b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 18670b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 18680b57cec5SDimitry Andric 18690b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @synchronized location"); 18700b57cec5SDimitry Andric 18710b57cec5SDimitry Andric std::string buf; 18720b57cec5SDimitry Andric SourceLocation SynchLoc = S->getAtSynchronizedLoc(); 18730b57cec5SDimitry Andric ConvertSourceLocationToLineDirective(SynchLoc, buf); 18740b57cec5SDimitry Andric buf += "{ id _rethrow = 0; id _sync_obj = (id)"; 18750b57cec5SDimitry Andric 18760b57cec5SDimitry Andric const char *lparenBuf = startBuf; 18770b57cec5SDimitry Andric while (*lparenBuf != '(') lparenBuf++; 18780b57cec5SDimitry Andric ReplaceText(startLoc, lparenBuf-startBuf+1, buf); 18790b57cec5SDimitry Andric 18800b57cec5SDimitry Andric buf = "; objc_sync_enter(_sync_obj);\n"; 18810b57cec5SDimitry Andric buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}"; 18820b57cec5SDimitry Andric buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}"; 18830b57cec5SDimitry Andric buf += "\n\tid sync_exit;"; 18840b57cec5SDimitry Andric buf += "\n\t} _sync_exit(_sync_obj);\n"; 18850b57cec5SDimitry Andric 18860b57cec5SDimitry Andric // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since 18870b57cec5SDimitry Andric // the sync expression is typically a message expression that's already 18880b57cec5SDimitry Andric // been rewritten! (which implies the SourceLocation's are invalid). 18890b57cec5SDimitry Andric SourceLocation RParenExprLoc = S->getSynchBody()->getBeginLoc(); 18900b57cec5SDimitry Andric const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc); 18910b57cec5SDimitry Andric while (*RParenExprLocBuf != ')') RParenExprLocBuf--; 18920b57cec5SDimitry Andric RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf); 18930b57cec5SDimitry Andric 18940b57cec5SDimitry Andric SourceLocation LBranceLoc = S->getSynchBody()->getBeginLoc(); 18950b57cec5SDimitry Andric const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc); 18960b57cec5SDimitry Andric assert (*LBraceLocBuf == '{'); 18970b57cec5SDimitry Andric ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf); 18980b57cec5SDimitry Andric 18990b57cec5SDimitry Andric SourceLocation startRBraceLoc = S->getSynchBody()->getEndLoc(); 19000b57cec5SDimitry Andric assert((*SM->getCharacterData(startRBraceLoc) == '}') && 19010b57cec5SDimitry Andric "bogus @synchronized block"); 19020b57cec5SDimitry Andric 19030b57cec5SDimitry Andric buf = "} catch (id e) {_rethrow = e;}\n"; 19040b57cec5SDimitry Andric Write_RethrowObject(buf); 19050b57cec5SDimitry Andric buf += "}\n"; 19060b57cec5SDimitry Andric buf += "}\n"; 19070b57cec5SDimitry Andric 19080b57cec5SDimitry Andric ReplaceText(startRBraceLoc, 1, buf); 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric return nullptr; 19110b57cec5SDimitry Andric } 19120b57cec5SDimitry Andric 19130b57cec5SDimitry Andric void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S) 19140b57cec5SDimitry Andric { 19150b57cec5SDimitry Andric // Perform a bottom up traversal of all children. 19160b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 19170b57cec5SDimitry Andric if (SubStmt) 19180b57cec5SDimitry Andric WarnAboutReturnGotoStmts(SubStmt); 19190b57cec5SDimitry Andric 19200b57cec5SDimitry Andric if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) { 19210b57cec5SDimitry Andric Diags.Report(Context->getFullLoc(S->getBeginLoc()), 19220b57cec5SDimitry Andric TryFinallyContainsReturnDiag); 19230b57cec5SDimitry Andric } 19240b57cec5SDimitry Andric } 19250b57cec5SDimitry Andric 19260b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { 19270b57cec5SDimitry Andric SourceLocation startLoc = S->getAtLoc(); 19280b57cec5SDimitry Andric ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */"); 19290b57cec5SDimitry Andric ReplaceText(S->getSubStmt()->getBeginLoc(), 1, 19300b57cec5SDimitry Andric "{ __AtAutoreleasePool __autoreleasepool; "); 19310b57cec5SDimitry Andric 19320b57cec5SDimitry Andric return nullptr; 19330b57cec5SDimitry Andric } 19340b57cec5SDimitry Andric 19350b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { 19360b57cec5SDimitry Andric ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt(); 19370b57cec5SDimitry Andric bool noCatch = S->getNumCatchStmts() == 0; 19380b57cec5SDimitry Andric std::string buf; 19390b57cec5SDimitry Andric SourceLocation TryLocation = S->getAtTryLoc(); 19400b57cec5SDimitry Andric ConvertSourceLocationToLineDirective(TryLocation, buf); 19410b57cec5SDimitry Andric 19420b57cec5SDimitry Andric if (finalStmt) { 19430b57cec5SDimitry Andric if (noCatch) 19440b57cec5SDimitry Andric buf += "{ id volatile _rethrow = 0;\n"; 19450b57cec5SDimitry Andric else { 19460b57cec5SDimitry Andric buf += "{ id volatile _rethrow = 0;\ntry {\n"; 19470b57cec5SDimitry Andric } 19480b57cec5SDimitry Andric } 19490b57cec5SDimitry Andric // Get the start location and compute the semi location. 19500b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 19510b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 19520b57cec5SDimitry Andric 19530b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @try location"); 19540b57cec5SDimitry Andric if (finalStmt) 19550b57cec5SDimitry Andric ReplaceText(startLoc, 1, buf); 19560b57cec5SDimitry Andric else 19570b57cec5SDimitry Andric // @try -> try 19580b57cec5SDimitry Andric ReplaceText(startLoc, 1, ""); 19590b57cec5SDimitry Andric 1960349cc55cSDimitry Andric for (ObjCAtCatchStmt *Catch : S->catch_stmts()) { 19610b57cec5SDimitry Andric VarDecl *catchDecl = Catch->getCatchParamDecl(); 19620b57cec5SDimitry Andric 19630b57cec5SDimitry Andric startLoc = Catch->getBeginLoc(); 19640b57cec5SDimitry Andric bool AtRemoved = false; 19650b57cec5SDimitry Andric if (catchDecl) { 19660b57cec5SDimitry Andric QualType t = catchDecl->getType(); 1967349cc55cSDimitry Andric if (const ObjCObjectPointerType *Ptr = 1968349cc55cSDimitry Andric t->getAs<ObjCObjectPointerType>()) { 19690b57cec5SDimitry Andric // Should be a pointer to a class. 19700b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface(); 19710b57cec5SDimitry Andric if (IDecl) { 19720b57cec5SDimitry Andric std::string Result; 19730b57cec5SDimitry Andric ConvertSourceLocationToLineDirective(Catch->getBeginLoc(), Result); 19740b57cec5SDimitry Andric 19750b57cec5SDimitry Andric startBuf = SM->getCharacterData(startLoc); 19760b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @catch location"); 19770b57cec5SDimitry Andric SourceLocation rParenLoc = Catch->getRParenLoc(); 19780b57cec5SDimitry Andric const char *rParenBuf = SM->getCharacterData(rParenLoc); 19790b57cec5SDimitry Andric 19800b57cec5SDimitry Andric // _objc_exc_Foo *_e as argument to catch. 19810b57cec5SDimitry Andric Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString(); 19820b57cec5SDimitry Andric Result += " *_"; Result += catchDecl->getNameAsString(); 19830b57cec5SDimitry Andric Result += ")"; 19840b57cec5SDimitry Andric ReplaceText(startLoc, rParenBuf-startBuf+1, Result); 19850b57cec5SDimitry Andric // Foo *e = (Foo *)_e; 19860b57cec5SDimitry Andric Result.clear(); 19870b57cec5SDimitry Andric Result = "{ "; 19880b57cec5SDimitry Andric Result += IDecl->getNameAsString(); 19890b57cec5SDimitry Andric Result += " *"; Result += catchDecl->getNameAsString(); 19900b57cec5SDimitry Andric Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)"; 19910b57cec5SDimitry Andric Result += "_"; Result += catchDecl->getNameAsString(); 19920b57cec5SDimitry Andric 19930b57cec5SDimitry Andric Result += "; "; 19940b57cec5SDimitry Andric SourceLocation lBraceLoc = Catch->getCatchBody()->getBeginLoc(); 19950b57cec5SDimitry Andric ReplaceText(lBraceLoc, 1, Result); 19960b57cec5SDimitry Andric AtRemoved = true; 19970b57cec5SDimitry Andric } 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric } 20000b57cec5SDimitry Andric if (!AtRemoved) 20010b57cec5SDimitry Andric // @catch -> catch 20020b57cec5SDimitry Andric ReplaceText(startLoc, 1, ""); 20030b57cec5SDimitry Andric 20040b57cec5SDimitry Andric } 20050b57cec5SDimitry Andric if (finalStmt) { 20060b57cec5SDimitry Andric buf.clear(); 20070b57cec5SDimitry Andric SourceLocation FinallyLoc = finalStmt->getBeginLoc(); 20080b57cec5SDimitry Andric 20090b57cec5SDimitry Andric if (noCatch) { 20100b57cec5SDimitry Andric ConvertSourceLocationToLineDirective(FinallyLoc, buf); 20110b57cec5SDimitry Andric buf += "catch (id e) {_rethrow = e;}\n"; 20120b57cec5SDimitry Andric } 20130b57cec5SDimitry Andric else { 20140b57cec5SDimitry Andric buf += "}\n"; 20150b57cec5SDimitry Andric ConvertSourceLocationToLineDirective(FinallyLoc, buf); 20160b57cec5SDimitry Andric buf += "catch (id e) {_rethrow = e;}\n"; 20170b57cec5SDimitry Andric } 20180b57cec5SDimitry Andric 20190b57cec5SDimitry Andric SourceLocation startFinalLoc = finalStmt->getBeginLoc(); 20200b57cec5SDimitry Andric ReplaceText(startFinalLoc, 8, buf); 20210b57cec5SDimitry Andric Stmt *body = finalStmt->getFinallyBody(); 20220b57cec5SDimitry Andric SourceLocation startFinalBodyLoc = body->getBeginLoc(); 20230b57cec5SDimitry Andric buf.clear(); 20240b57cec5SDimitry Andric Write_RethrowObject(buf); 20250b57cec5SDimitry Andric ReplaceText(startFinalBodyLoc, 1, buf); 20260b57cec5SDimitry Andric 20270b57cec5SDimitry Andric SourceLocation endFinalBodyLoc = body->getEndLoc(); 20280b57cec5SDimitry Andric ReplaceText(endFinalBodyLoc, 1, "}\n}"); 20290b57cec5SDimitry Andric // Now check for any return/continue/go statements within the @try. 20300b57cec5SDimitry Andric WarnAboutReturnGotoStmts(S->getTryBody()); 20310b57cec5SDimitry Andric } 20320b57cec5SDimitry Andric 20330b57cec5SDimitry Andric return nullptr; 20340b57cec5SDimitry Andric } 20350b57cec5SDimitry Andric 20360b57cec5SDimitry Andric // This can't be done with ReplaceStmt(S, ThrowExpr), since 20370b57cec5SDimitry Andric // the throw expression is typically a message expression that's already 20380b57cec5SDimitry Andric // been rewritten! (which implies the SourceLocation's are invalid). 20390b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { 20400b57cec5SDimitry Andric // Get the start location and compute the semi location. 20410b57cec5SDimitry Andric SourceLocation startLoc = S->getBeginLoc(); 20420b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 20430b57cec5SDimitry Andric 20440b57cec5SDimitry Andric assert((*startBuf == '@') && "bogus @throw location"); 20450b57cec5SDimitry Andric 20460b57cec5SDimitry Andric std::string buf; 20470b57cec5SDimitry Andric /* void objc_exception_throw(id) __attribute__((noreturn)); */ 20480b57cec5SDimitry Andric if (S->getThrowExpr()) 20490b57cec5SDimitry Andric buf = "objc_exception_throw("; 20500b57cec5SDimitry Andric else 20510b57cec5SDimitry Andric buf = "throw"; 20520b57cec5SDimitry Andric 20530b57cec5SDimitry Andric // handle "@ throw" correctly. 20540b57cec5SDimitry Andric const char *wBuf = strchr(startBuf, 'w'); 20550b57cec5SDimitry Andric assert((*wBuf == 'w') && "@throw: can't find 'w'"); 20560b57cec5SDimitry Andric ReplaceText(startLoc, wBuf-startBuf+1, buf); 20570b57cec5SDimitry Andric 20580b57cec5SDimitry Andric SourceLocation endLoc = S->getEndLoc(); 20590b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(endLoc); 20600b57cec5SDimitry Andric const char *semiBuf = strchr(endBuf, ';'); 20610b57cec5SDimitry Andric assert((*semiBuf == ';') && "@throw: can't find ';'"); 20620b57cec5SDimitry Andric SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf); 20630b57cec5SDimitry Andric if (S->getThrowExpr()) 20640b57cec5SDimitry Andric ReplaceText(semiLoc, 1, ");"); 20650b57cec5SDimitry Andric return nullptr; 20660b57cec5SDimitry Andric } 20670b57cec5SDimitry Andric 20680b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { 20690b57cec5SDimitry Andric // Create a new string expression. 20700b57cec5SDimitry Andric std::string StrEncoding; 20710b57cec5SDimitry Andric Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); 20720b57cec5SDimitry Andric Expr *Replacement = getStringLiteral(StrEncoding); 20730b57cec5SDimitry Andric ReplaceStmt(Exp, Replacement); 20740b57cec5SDimitry Andric 20750b57cec5SDimitry Andric // Replace this subexpr in the parent. 20760b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 20770b57cec5SDimitry Andric return Replacement; 20780b57cec5SDimitry Andric } 20790b57cec5SDimitry Andric 20800b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { 20810b57cec5SDimitry Andric if (!SelGetUidFunctionDecl) 20820b57cec5SDimitry Andric SynthSelGetUidFunctionDecl(); 20830b57cec5SDimitry Andric assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl"); 20840b57cec5SDimitry Andric // Create a call to sel_registerName("selName"). 20850b57cec5SDimitry Andric SmallVector<Expr*, 8> SelExprs; 20860b57cec5SDimitry Andric SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString())); 20870b57cec5SDimitry Andric CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 20880b57cec5SDimitry Andric SelExprs); 20890b57cec5SDimitry Andric ReplaceStmt(Exp, SelExp); 20900b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 20910b57cec5SDimitry Andric return SelExp; 20920b57cec5SDimitry Andric } 20930b57cec5SDimitry Andric 20940b57cec5SDimitry Andric CallExpr * 20950b57cec5SDimitry Andric RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD, 20960b57cec5SDimitry Andric ArrayRef<Expr *> Args, 20970b57cec5SDimitry Andric SourceLocation StartLoc, 20980b57cec5SDimitry Andric SourceLocation EndLoc) { 20990b57cec5SDimitry Andric // Get the type, we will need to reference it in a couple spots. 21000b57cec5SDimitry Andric QualType msgSendType = FD->getType(); 21010b57cec5SDimitry Andric 21020b57cec5SDimitry Andric // Create a reference to the objc_msgSend() declaration. 21030b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType, 21040b57cec5SDimitry Andric VK_LValue, SourceLocation()); 21050b57cec5SDimitry Andric 21060b57cec5SDimitry Andric // Now, we cast the reference to a pointer to the objc_msgSend type. 21070b57cec5SDimitry Andric QualType pToFunc = Context->getPointerType(msgSendType); 21080b57cec5SDimitry Andric ImplicitCastExpr *ICE = 21090b57cec5SDimitry Andric ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, 2110fe6060f1SDimitry Andric DRE, nullptr, VK_PRValue, FPOptionsOverride()); 21110b57cec5SDimitry Andric 2112a7dea167SDimitry Andric const auto *FT = msgSendType->castAs<FunctionType>(); 2113e8d8bef9SDimitry Andric CallExpr *Exp = 2114e8d8bef9SDimitry Andric CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context), 2115fe6060f1SDimitry Andric VK_PRValue, EndLoc, FPOptionsOverride()); 21160b57cec5SDimitry Andric return Exp; 21170b57cec5SDimitry Andric } 21180b57cec5SDimitry Andric 21190b57cec5SDimitry Andric static bool scanForProtocolRefs(const char *startBuf, const char *endBuf, 21200b57cec5SDimitry Andric const char *&startRef, const char *&endRef) { 21210b57cec5SDimitry Andric while (startBuf < endBuf) { 21220b57cec5SDimitry Andric if (*startBuf == '<') 21230b57cec5SDimitry Andric startRef = startBuf; // mark the start. 21240b57cec5SDimitry Andric if (*startBuf == '>') { 21250b57cec5SDimitry Andric if (startRef && *startRef == '<') { 21260b57cec5SDimitry Andric endRef = startBuf; // mark the end. 21270b57cec5SDimitry Andric return true; 21280b57cec5SDimitry Andric } 21290b57cec5SDimitry Andric return false; 21300b57cec5SDimitry Andric } 21310b57cec5SDimitry Andric startBuf++; 21320b57cec5SDimitry Andric } 21330b57cec5SDimitry Andric return false; 21340b57cec5SDimitry Andric } 21350b57cec5SDimitry Andric 21360b57cec5SDimitry Andric static void scanToNextArgument(const char *&argRef) { 21370b57cec5SDimitry Andric int angle = 0; 21380b57cec5SDimitry Andric while (*argRef != ')' && (*argRef != ',' || angle > 0)) { 21390b57cec5SDimitry Andric if (*argRef == '<') 21400b57cec5SDimitry Andric angle++; 21410b57cec5SDimitry Andric else if (*argRef == '>') 21420b57cec5SDimitry Andric angle--; 21430b57cec5SDimitry Andric argRef++; 21440b57cec5SDimitry Andric } 21450b57cec5SDimitry Andric assert(angle == 0 && "scanToNextArgument - bad protocol type syntax"); 21460b57cec5SDimitry Andric } 21470b57cec5SDimitry Andric 21480b57cec5SDimitry Andric bool RewriteModernObjC::needToScanForQualifiers(QualType T) { 21490b57cec5SDimitry Andric if (T->isObjCQualifiedIdType()) 21500b57cec5SDimitry Andric return true; 21510b57cec5SDimitry Andric if (const PointerType *PT = T->getAs<PointerType>()) { 21520b57cec5SDimitry Andric if (PT->getPointeeType()->isObjCQualifiedIdType()) 21530b57cec5SDimitry Andric return true; 21540b57cec5SDimitry Andric } 21550b57cec5SDimitry Andric if (T->isObjCObjectPointerType()) { 21560b57cec5SDimitry Andric T = T->getPointeeType(); 21570b57cec5SDimitry Andric return T->isObjCQualifiedInterfaceType(); 21580b57cec5SDimitry Andric } 21590b57cec5SDimitry Andric if (T->isArrayType()) { 21600b57cec5SDimitry Andric QualType ElemTy = Context->getBaseElementType(T); 21610b57cec5SDimitry Andric return needToScanForQualifiers(ElemTy); 21620b57cec5SDimitry Andric } 21630b57cec5SDimitry Andric return false; 21640b57cec5SDimitry Andric } 21650b57cec5SDimitry Andric 21660b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { 21670b57cec5SDimitry Andric QualType Type = E->getType(); 21680b57cec5SDimitry Andric if (needToScanForQualifiers(Type)) { 21690b57cec5SDimitry Andric SourceLocation Loc, EndLoc; 21700b57cec5SDimitry Andric 21710b57cec5SDimitry Andric if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { 21720b57cec5SDimitry Andric Loc = ECE->getLParenLoc(); 21730b57cec5SDimitry Andric EndLoc = ECE->getRParenLoc(); 21740b57cec5SDimitry Andric } else { 21750b57cec5SDimitry Andric Loc = E->getBeginLoc(); 21760b57cec5SDimitry Andric EndLoc = E->getEndLoc(); 21770b57cec5SDimitry Andric } 21780b57cec5SDimitry Andric // This will defend against trying to rewrite synthesized expressions. 21790b57cec5SDimitry Andric if (Loc.isInvalid() || EndLoc.isInvalid()) 21800b57cec5SDimitry Andric return; 21810b57cec5SDimitry Andric 21820b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(Loc); 21830b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(EndLoc); 21840b57cec5SDimitry Andric const char *startRef = nullptr, *endRef = nullptr; 21850b57cec5SDimitry Andric if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 21860b57cec5SDimitry Andric // Get the locations of the startRef, endRef. 21870b57cec5SDimitry Andric SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf); 21880b57cec5SDimitry Andric SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1); 21890b57cec5SDimitry Andric // Comment out the protocol references. 21900b57cec5SDimitry Andric InsertText(LessLoc, "/*"); 21910b57cec5SDimitry Andric InsertText(GreaterLoc, "*/"); 21920b57cec5SDimitry Andric } 21930b57cec5SDimitry Andric } 21940b57cec5SDimitry Andric } 21950b57cec5SDimitry Andric 21960b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { 21970b57cec5SDimitry Andric SourceLocation Loc; 21980b57cec5SDimitry Andric QualType Type; 21990b57cec5SDimitry Andric const FunctionProtoType *proto = nullptr; 22000b57cec5SDimitry Andric if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) { 22010b57cec5SDimitry Andric Loc = VD->getLocation(); 22020b57cec5SDimitry Andric Type = VD->getType(); 22030b57cec5SDimitry Andric } 22040b57cec5SDimitry Andric else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) { 22050b57cec5SDimitry Andric Loc = FD->getLocation(); 22060b57cec5SDimitry Andric // Check for ObjC 'id' and class types that have been adorned with protocol 22070b57cec5SDimitry Andric // information (id<p>, C<p>*). The protocol references need to be rewritten! 22080b57cec5SDimitry Andric const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 22090b57cec5SDimitry Andric assert(funcType && "missing function type"); 22100b57cec5SDimitry Andric proto = dyn_cast<FunctionProtoType>(funcType); 22110b57cec5SDimitry Andric if (!proto) 22120b57cec5SDimitry Andric return; 22130b57cec5SDimitry Andric Type = proto->getReturnType(); 22140b57cec5SDimitry Andric } 22150b57cec5SDimitry Andric else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) { 22160b57cec5SDimitry Andric Loc = FD->getLocation(); 22170b57cec5SDimitry Andric Type = FD->getType(); 22180b57cec5SDimitry Andric } 22190b57cec5SDimitry Andric else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) { 22200b57cec5SDimitry Andric Loc = TD->getLocation(); 22210b57cec5SDimitry Andric Type = TD->getUnderlyingType(); 22220b57cec5SDimitry Andric } 22230b57cec5SDimitry Andric else 22240b57cec5SDimitry Andric return; 22250b57cec5SDimitry Andric 22260b57cec5SDimitry Andric if (needToScanForQualifiers(Type)) { 22270b57cec5SDimitry Andric // Since types are unique, we need to scan the buffer. 22280b57cec5SDimitry Andric 22290b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(Loc); 22300b57cec5SDimitry Andric const char *startBuf = endBuf; 22310b57cec5SDimitry Andric while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) 22320b57cec5SDimitry Andric startBuf--; // scan backward (from the decl location) for return type. 22330b57cec5SDimitry Andric const char *startRef = nullptr, *endRef = nullptr; 22340b57cec5SDimitry Andric if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 22350b57cec5SDimitry Andric // Get the locations of the startRef, endRef. 22360b57cec5SDimitry Andric SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf); 22370b57cec5SDimitry Andric SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1); 22380b57cec5SDimitry Andric // Comment out the protocol references. 22390b57cec5SDimitry Andric InsertText(LessLoc, "/*"); 22400b57cec5SDimitry Andric InsertText(GreaterLoc, "*/"); 22410b57cec5SDimitry Andric } 22420b57cec5SDimitry Andric } 22430b57cec5SDimitry Andric if (!proto) 22440b57cec5SDimitry Andric return; // most likely, was a variable 22450b57cec5SDimitry Andric // Now check arguments. 22460b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(Loc); 22470b57cec5SDimitry Andric const char *startFuncBuf = startBuf; 22480b57cec5SDimitry Andric for (unsigned i = 0; i < proto->getNumParams(); i++) { 22490b57cec5SDimitry Andric if (needToScanForQualifiers(proto->getParamType(i))) { 22500b57cec5SDimitry Andric // Since types are unique, we need to scan the buffer. 22510b57cec5SDimitry Andric 22520b57cec5SDimitry Andric const char *endBuf = startBuf; 22530b57cec5SDimitry Andric // scan forward (from the decl location) for argument types. 22540b57cec5SDimitry Andric scanToNextArgument(endBuf); 22550b57cec5SDimitry Andric const char *startRef = nullptr, *endRef = nullptr; 22560b57cec5SDimitry Andric if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 22570b57cec5SDimitry Andric // Get the locations of the startRef, endRef. 22580b57cec5SDimitry Andric SourceLocation LessLoc = 22590b57cec5SDimitry Andric Loc.getLocWithOffset(startRef-startFuncBuf); 22600b57cec5SDimitry Andric SourceLocation GreaterLoc = 22610b57cec5SDimitry Andric Loc.getLocWithOffset(endRef-startFuncBuf+1); 22620b57cec5SDimitry Andric // Comment out the protocol references. 22630b57cec5SDimitry Andric InsertText(LessLoc, "/*"); 22640b57cec5SDimitry Andric InsertText(GreaterLoc, "*/"); 22650b57cec5SDimitry Andric } 22660b57cec5SDimitry Andric startBuf = ++endBuf; 22670b57cec5SDimitry Andric } 22680b57cec5SDimitry Andric else { 22690b57cec5SDimitry Andric // If the function name is derived from a macro expansion, then the 22700b57cec5SDimitry Andric // argument buffer will not follow the name. Need to speak with Chris. 22710b57cec5SDimitry Andric while (*startBuf && *startBuf != ')' && *startBuf != ',') 22720b57cec5SDimitry Andric startBuf++; // scan forward (from the decl location) for argument types. 22730b57cec5SDimitry Andric startBuf++; 22740b57cec5SDimitry Andric } 22750b57cec5SDimitry Andric } 22760b57cec5SDimitry Andric } 22770b57cec5SDimitry Andric 22780b57cec5SDimitry Andric void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) { 22790b57cec5SDimitry Andric QualType QT = ND->getType(); 22800b57cec5SDimitry Andric const Type* TypePtr = QT->getAs<Type>(); 22810b57cec5SDimitry Andric if (!isa<TypeOfExprType>(TypePtr)) 22820b57cec5SDimitry Andric return; 22830b57cec5SDimitry Andric while (isa<TypeOfExprType>(TypePtr)) { 22840b57cec5SDimitry Andric const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 22850b57cec5SDimitry Andric QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 22860b57cec5SDimitry Andric TypePtr = QT->getAs<Type>(); 22870b57cec5SDimitry Andric } 22880b57cec5SDimitry Andric // FIXME. This will not work for multiple declarators; as in: 22890b57cec5SDimitry Andric // __typeof__(a) b,c,d; 22900b57cec5SDimitry Andric std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy())); 22910b57cec5SDimitry Andric SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 22920b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(DeclLoc); 22930b57cec5SDimitry Andric if (ND->getInit()) { 22940b57cec5SDimitry Andric std::string Name(ND->getNameAsString()); 22950b57cec5SDimitry Andric TypeAsString += " " + Name + " = "; 22960b57cec5SDimitry Andric Expr *E = ND->getInit(); 22970b57cec5SDimitry Andric SourceLocation startLoc; 22980b57cec5SDimitry Andric if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 22990b57cec5SDimitry Andric startLoc = ECE->getLParenLoc(); 23000b57cec5SDimitry Andric else 23010b57cec5SDimitry Andric startLoc = E->getBeginLoc(); 23020b57cec5SDimitry Andric startLoc = SM->getExpansionLoc(startLoc); 23030b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(startLoc); 23040b57cec5SDimitry Andric ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 23050b57cec5SDimitry Andric } 23060b57cec5SDimitry Andric else { 23070b57cec5SDimitry Andric SourceLocation X = ND->getEndLoc(); 23080b57cec5SDimitry Andric X = SM->getExpansionLoc(X); 23090b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(X); 23100b57cec5SDimitry Andric ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 23110b57cec5SDimitry Andric } 23120b57cec5SDimitry Andric } 23130b57cec5SDimitry Andric 23140b57cec5SDimitry Andric // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); 23150b57cec5SDimitry Andric void RewriteModernObjC::SynthSelGetUidFunctionDecl() { 23160b57cec5SDimitry Andric IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); 23170b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 23180b57cec5SDimitry Andric ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 23190b57cec5SDimitry Andric QualType getFuncType = 23200b57cec5SDimitry Andric getSimpleFunctionType(Context->getObjCSelType(), ArgTys); 23210b57cec5SDimitry Andric SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 23220b57cec5SDimitry Andric SourceLocation(), 23230b57cec5SDimitry Andric SourceLocation(), 23240b57cec5SDimitry Andric SelGetUidIdent, getFuncType, 23250b57cec5SDimitry Andric nullptr, SC_Extern); 23260b57cec5SDimitry Andric } 23270b57cec5SDimitry Andric 23280b57cec5SDimitry Andric void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) { 23290b57cec5SDimitry Andric // declared in <objc/objc.h> 23300b57cec5SDimitry Andric if (FD->getIdentifier() && 23310b57cec5SDimitry Andric FD->getName() == "sel_registerName") { 23320b57cec5SDimitry Andric SelGetUidFunctionDecl = FD; 23330b57cec5SDimitry Andric return; 23340b57cec5SDimitry Andric } 23350b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(FD); 23360b57cec5SDimitry Andric } 23370b57cec5SDimitry Andric 23380b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) { 23390b57cec5SDimitry Andric std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 23400b57cec5SDimitry Andric const char *argPtr = TypeString.c_str(); 23410b57cec5SDimitry Andric if (!strchr(argPtr, '^')) { 23420b57cec5SDimitry Andric Str += TypeString; 23430b57cec5SDimitry Andric return; 23440b57cec5SDimitry Andric } 23450b57cec5SDimitry Andric while (*argPtr) { 23460b57cec5SDimitry Andric Str += (*argPtr == '^' ? '*' : *argPtr); 23470b57cec5SDimitry Andric argPtr++; 23480b57cec5SDimitry Andric } 23490b57cec5SDimitry Andric } 23500b57cec5SDimitry Andric 23510b57cec5SDimitry Andric // FIXME. Consolidate this routine with RewriteBlockPointerType. 23520b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str, 23530b57cec5SDimitry Andric ValueDecl *VD) { 23540b57cec5SDimitry Andric QualType Type = VD->getType(); 23550b57cec5SDimitry Andric std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 23560b57cec5SDimitry Andric const char *argPtr = TypeString.c_str(); 23570b57cec5SDimitry Andric int paren = 0; 23580b57cec5SDimitry Andric while (*argPtr) { 23590b57cec5SDimitry Andric switch (*argPtr) { 23600b57cec5SDimitry Andric case '(': 23610b57cec5SDimitry Andric Str += *argPtr; 23620b57cec5SDimitry Andric paren++; 23630b57cec5SDimitry Andric break; 23640b57cec5SDimitry Andric case ')': 23650b57cec5SDimitry Andric Str += *argPtr; 23660b57cec5SDimitry Andric paren--; 23670b57cec5SDimitry Andric break; 23680b57cec5SDimitry Andric case '^': 23690b57cec5SDimitry Andric Str += '*'; 23700b57cec5SDimitry Andric if (paren == 1) 23710b57cec5SDimitry Andric Str += VD->getNameAsString(); 23720b57cec5SDimitry Andric break; 23730b57cec5SDimitry Andric default: 23740b57cec5SDimitry Andric Str += *argPtr; 23750b57cec5SDimitry Andric break; 23760b57cec5SDimitry Andric } 23770b57cec5SDimitry Andric argPtr++; 23780b57cec5SDimitry Andric } 23790b57cec5SDimitry Andric } 23800b57cec5SDimitry Andric 23810b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { 23820b57cec5SDimitry Andric SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 23830b57cec5SDimitry Andric const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 23840b57cec5SDimitry Andric const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType); 23850b57cec5SDimitry Andric if (!proto) 23860b57cec5SDimitry Andric return; 23870b57cec5SDimitry Andric QualType Type = proto->getReturnType(); 23880b57cec5SDimitry Andric std::string FdStr = Type.getAsString(Context->getPrintingPolicy()); 23890b57cec5SDimitry Andric FdStr += " "; 23900b57cec5SDimitry Andric FdStr += FD->getName(); 23910b57cec5SDimitry Andric FdStr += "("; 23920b57cec5SDimitry Andric unsigned numArgs = proto->getNumParams(); 23930b57cec5SDimitry Andric for (unsigned i = 0; i < numArgs; i++) { 23940b57cec5SDimitry Andric QualType ArgType = proto->getParamType(i); 23950b57cec5SDimitry Andric RewriteBlockPointerType(FdStr, ArgType); 23960b57cec5SDimitry Andric if (i+1 < numArgs) 23970b57cec5SDimitry Andric FdStr += ", "; 23980b57cec5SDimitry Andric } 23990b57cec5SDimitry Andric if (FD->isVariadic()) { 24000b57cec5SDimitry Andric FdStr += (numArgs > 0) ? ", ...);\n" : "...);\n"; 24010b57cec5SDimitry Andric } 24020b57cec5SDimitry Andric else 24030b57cec5SDimitry Andric FdStr += ");\n"; 24040b57cec5SDimitry Andric InsertText(FunLocStart, FdStr); 24050b57cec5SDimitry Andric } 24060b57cec5SDimitry Andric 24070b57cec5SDimitry Andric // SynthSuperConstructorFunctionDecl - id __rw_objc_super(id obj, id super); 24080b57cec5SDimitry Andric void RewriteModernObjC::SynthSuperConstructorFunctionDecl() { 24090b57cec5SDimitry Andric if (SuperConstructorFunctionDecl) 24100b57cec5SDimitry Andric return; 24110b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super"); 24120b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 24130b57cec5SDimitry Andric QualType argT = Context->getObjCIdType(); 24140b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'id' type"); 24150b57cec5SDimitry Andric ArgTys.push_back(argT); 24160b57cec5SDimitry Andric ArgTys.push_back(argT); 24170b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 24180b57cec5SDimitry Andric ArgTys); 24190b57cec5SDimitry Andric SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24200b57cec5SDimitry Andric SourceLocation(), 24210b57cec5SDimitry Andric SourceLocation(), 24220b57cec5SDimitry Andric msgSendIdent, msgSendType, 24230b57cec5SDimitry Andric nullptr, SC_Extern); 24240b57cec5SDimitry Andric } 24250b57cec5SDimitry Andric 24260b57cec5SDimitry Andric // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); 24270b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendFunctionDecl() { 24280b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend"); 24290b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 24300b57cec5SDimitry Andric QualType argT = Context->getObjCIdType(); 24310b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'id' type"); 24320b57cec5SDimitry Andric ArgTys.push_back(argT); 24330b57cec5SDimitry Andric argT = Context->getObjCSelType(); 24340b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'SEL' type"); 24350b57cec5SDimitry Andric ArgTys.push_back(argT); 24360b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 24370b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 24380b57cec5SDimitry Andric MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24390b57cec5SDimitry Andric SourceLocation(), 24400b57cec5SDimitry Andric SourceLocation(), 24410b57cec5SDimitry Andric msgSendIdent, msgSendType, nullptr, 24420b57cec5SDimitry Andric SC_Extern); 24430b57cec5SDimitry Andric } 24440b57cec5SDimitry Andric 24450b57cec5SDimitry Andric // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void); 24460b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() { 24470b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); 24480b57cec5SDimitry Andric SmallVector<QualType, 2> ArgTys; 24490b57cec5SDimitry Andric ArgTys.push_back(Context->VoidTy); 24500b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 24510b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 24520b57cec5SDimitry Andric MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24530b57cec5SDimitry Andric SourceLocation(), 24540b57cec5SDimitry Andric SourceLocation(), 24550b57cec5SDimitry Andric msgSendIdent, msgSendType, 24560b57cec5SDimitry Andric nullptr, SC_Extern); 24570b57cec5SDimitry Andric } 24580b57cec5SDimitry Andric 24590b57cec5SDimitry Andric // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); 24600b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendStretFunctionDecl() { 24610b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret"); 24620b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 24630b57cec5SDimitry Andric QualType argT = Context->getObjCIdType(); 24640b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'id' type"); 24650b57cec5SDimitry Andric ArgTys.push_back(argT); 24660b57cec5SDimitry Andric argT = Context->getObjCSelType(); 24670b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'SEL' type"); 24680b57cec5SDimitry Andric ArgTys.push_back(argT); 24690b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 24700b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 24710b57cec5SDimitry Andric MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24720b57cec5SDimitry Andric SourceLocation(), 24730b57cec5SDimitry Andric SourceLocation(), 24740b57cec5SDimitry Andric msgSendIdent, msgSendType, 24750b57cec5SDimitry Andric nullptr, SC_Extern); 24760b57cec5SDimitry Andric } 24770b57cec5SDimitry Andric 24780b57cec5SDimitry Andric // SynthMsgSendSuperStretFunctionDecl - 24790b57cec5SDimitry Andric // id objc_msgSendSuper_stret(void); 24800b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() { 24810b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = 24820b57cec5SDimitry Andric &Context->Idents.get("objc_msgSendSuper_stret"); 24830b57cec5SDimitry Andric SmallVector<QualType, 2> ArgTys; 24840b57cec5SDimitry Andric ArgTys.push_back(Context->VoidTy); 24850b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 24860b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 24870b57cec5SDimitry Andric MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24880b57cec5SDimitry Andric SourceLocation(), 24890b57cec5SDimitry Andric SourceLocation(), 24900b57cec5SDimitry Andric msgSendIdent, 24910b57cec5SDimitry Andric msgSendType, nullptr, 24920b57cec5SDimitry Andric SC_Extern); 24930b57cec5SDimitry Andric } 24940b57cec5SDimitry Andric 24950b57cec5SDimitry Andric // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); 24960b57cec5SDimitry Andric void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() { 24970b57cec5SDimitry Andric IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret"); 24980b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 24990b57cec5SDimitry Andric QualType argT = Context->getObjCIdType(); 25000b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'id' type"); 25010b57cec5SDimitry Andric ArgTys.push_back(argT); 25020b57cec5SDimitry Andric argT = Context->getObjCSelType(); 25030b57cec5SDimitry Andric assert(!argT.isNull() && "Can't find 'SEL' type"); 25040b57cec5SDimitry Andric ArgTys.push_back(argT); 25050b57cec5SDimitry Andric QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, 25060b57cec5SDimitry Andric ArgTys, /*variadic=*/true); 25070b57cec5SDimitry Andric MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25080b57cec5SDimitry Andric SourceLocation(), 25090b57cec5SDimitry Andric SourceLocation(), 25100b57cec5SDimitry Andric msgSendIdent, msgSendType, 25110b57cec5SDimitry Andric nullptr, SC_Extern); 25120b57cec5SDimitry Andric } 25130b57cec5SDimitry Andric 25140b57cec5SDimitry Andric // SynthGetClassFunctionDecl - Class objc_getClass(const char *name); 25150b57cec5SDimitry Andric void RewriteModernObjC::SynthGetClassFunctionDecl() { 25160b57cec5SDimitry Andric IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); 25170b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 25180b57cec5SDimitry Andric ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 25190b57cec5SDimitry Andric QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 25200b57cec5SDimitry Andric ArgTys); 25210b57cec5SDimitry Andric GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25220b57cec5SDimitry Andric SourceLocation(), 25230b57cec5SDimitry Andric SourceLocation(), 25240b57cec5SDimitry Andric getClassIdent, getClassType, 25250b57cec5SDimitry Andric nullptr, SC_Extern); 25260b57cec5SDimitry Andric } 25270b57cec5SDimitry Andric 25280b57cec5SDimitry Andric // SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); 25290b57cec5SDimitry Andric void RewriteModernObjC::SynthGetSuperClassFunctionDecl() { 25300b57cec5SDimitry Andric IdentifierInfo *getSuperClassIdent = 25310b57cec5SDimitry Andric &Context->Idents.get("class_getSuperclass"); 25320b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 25330b57cec5SDimitry Andric ArgTys.push_back(Context->getObjCClassType()); 25340b57cec5SDimitry Andric QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 25350b57cec5SDimitry Andric ArgTys); 25360b57cec5SDimitry Andric GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25370b57cec5SDimitry Andric SourceLocation(), 25380b57cec5SDimitry Andric SourceLocation(), 25390b57cec5SDimitry Andric getSuperClassIdent, 25400b57cec5SDimitry Andric getClassType, nullptr, 25410b57cec5SDimitry Andric SC_Extern); 25420b57cec5SDimitry Andric } 25430b57cec5SDimitry Andric 25440b57cec5SDimitry Andric // SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name); 25450b57cec5SDimitry Andric void RewriteModernObjC::SynthGetMetaClassFunctionDecl() { 25460b57cec5SDimitry Andric IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); 25470b57cec5SDimitry Andric SmallVector<QualType, 16> ArgTys; 25480b57cec5SDimitry Andric ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 25490b57cec5SDimitry Andric QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 25500b57cec5SDimitry Andric ArgTys); 25510b57cec5SDimitry Andric GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25520b57cec5SDimitry Andric SourceLocation(), 25530b57cec5SDimitry Andric SourceLocation(), 25540b57cec5SDimitry Andric getClassIdent, getClassType, 25550b57cec5SDimitry Andric nullptr, SC_Extern); 25560b57cec5SDimitry Andric } 25570b57cec5SDimitry Andric 25580b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { 25590b57cec5SDimitry Andric assert (Exp != nullptr && "Expected non-null ObjCStringLiteral"); 25600b57cec5SDimitry Andric QualType strType = getConstantStringStructType(); 25610b57cec5SDimitry Andric 25620b57cec5SDimitry Andric std::string S = "__NSConstantStringImpl_"; 25630b57cec5SDimitry Andric 25640b57cec5SDimitry Andric std::string tmpName = InFileName; 25650b57cec5SDimitry Andric unsigned i; 25660b57cec5SDimitry Andric for (i=0; i < tmpName.length(); i++) { 25670b57cec5SDimitry Andric char c = tmpName.at(i); 25680b57cec5SDimitry Andric // replace any non-alphanumeric characters with '_'. 25690b57cec5SDimitry Andric if (!isAlphanumeric(c)) 25700b57cec5SDimitry Andric tmpName[i] = '_'; 25710b57cec5SDimitry Andric } 25720b57cec5SDimitry Andric S += tmpName; 25730b57cec5SDimitry Andric S += "_"; 25740b57cec5SDimitry Andric S += utostr(NumObjCStringLiterals++); 25750b57cec5SDimitry Andric 25760b57cec5SDimitry Andric Preamble += "static __NSConstantStringImpl " + S; 25770b57cec5SDimitry Andric Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,"; 25780b57cec5SDimitry Andric Preamble += "0x000007c8,"; // utf8_str 25790b57cec5SDimitry Andric // The pretty printer for StringLiteral handles escape characters properly. 25800b57cec5SDimitry Andric std::string prettyBufS; 25810b57cec5SDimitry Andric llvm::raw_string_ostream prettyBuf(prettyBufS); 25820b57cec5SDimitry Andric Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts)); 2583*0fca6ea1SDimitry Andric Preamble += prettyBufS; 25840b57cec5SDimitry Andric Preamble += ","; 25850b57cec5SDimitry Andric Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; 25860b57cec5SDimitry Andric 25870b57cec5SDimitry Andric VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 25880b57cec5SDimitry Andric SourceLocation(), &Context->Idents.get(S), 25890b57cec5SDimitry Andric strType, nullptr, SC_Static); 25900b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 25910b57cec5SDimitry Andric DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation()); 25925ffd83dbSDimitry Andric Expr *Unop = UnaryOperator::Create( 25935ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), DRE, UO_AddrOf, 2594fe6060f1SDimitry Andric Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary, 25955ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 25960b57cec5SDimitry Andric // cast to NSConstantString * 25970b57cec5SDimitry Andric CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), 25980b57cec5SDimitry Andric CK_CPointerToObjCPointerCast, Unop); 25990b57cec5SDimitry Andric ReplaceStmt(Exp, cast); 26000b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 26010b57cec5SDimitry Andric return cast; 26020b57cec5SDimitry Andric } 26030b57cec5SDimitry Andric 26040b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) { 26050b57cec5SDimitry Andric unsigned IntSize = 26060b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 26070b57cec5SDimitry Andric 26080b57cec5SDimitry Andric Expr *FlagExp = IntegerLiteral::Create(*Context, 26090b57cec5SDimitry Andric llvm::APInt(IntSize, Exp->getValue()), 26100b57cec5SDimitry Andric Context->IntTy, Exp->getLocation()); 26110b57cec5SDimitry Andric CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy, 26120b57cec5SDimitry Andric CK_BitCast, FlagExp); 26130b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(), 26140b57cec5SDimitry Andric cast); 26150b57cec5SDimitry Andric ReplaceStmt(Exp, PE); 26160b57cec5SDimitry Andric return PE; 26170b57cec5SDimitry Andric } 26180b57cec5SDimitry Andric 26190b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) { 26200b57cec5SDimitry Andric // synthesize declaration of helper functions needed in this routine. 26210b57cec5SDimitry Andric if (!SelGetUidFunctionDecl) 26220b57cec5SDimitry Andric SynthSelGetUidFunctionDecl(); 26230b57cec5SDimitry Andric // use objc_msgSend() for all. 26240b57cec5SDimitry Andric if (!MsgSendFunctionDecl) 26250b57cec5SDimitry Andric SynthMsgSendFunctionDecl(); 26260b57cec5SDimitry Andric if (!GetClassFunctionDecl) 26270b57cec5SDimitry Andric SynthGetClassFunctionDecl(); 26280b57cec5SDimitry Andric 26290b57cec5SDimitry Andric FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 26300b57cec5SDimitry Andric SourceLocation StartLoc = Exp->getBeginLoc(); 26310b57cec5SDimitry Andric SourceLocation EndLoc = Exp->getEndLoc(); 26320b57cec5SDimitry Andric 26330b57cec5SDimitry Andric // Synthesize a call to objc_msgSend(). 26340b57cec5SDimitry Andric SmallVector<Expr*, 4> MsgExprs; 26350b57cec5SDimitry Andric SmallVector<Expr*, 4> ClsExprs; 26360b57cec5SDimitry Andric 26370b57cec5SDimitry Andric // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument. 26380b57cec5SDimitry Andric ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod(); 26390b57cec5SDimitry Andric ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface(); 26400b57cec5SDimitry Andric 26410b57cec5SDimitry Andric IdentifierInfo *clsName = BoxingClass->getIdentifier(); 26420b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(clsName->getName())); 26430b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs, 26440b57cec5SDimitry Andric StartLoc, EndLoc); 26450b57cec5SDimitry Andric MsgExprs.push_back(Cls); 26460b57cec5SDimitry Andric 26470b57cec5SDimitry Andric // Create a call to sel_registerName("<BoxingMethod>:"), etc. 26480b57cec5SDimitry Andric // it will be the 2nd argument. 26490b57cec5SDimitry Andric SmallVector<Expr*, 4> SelExprs; 26500b57cec5SDimitry Andric SelExprs.push_back( 26510b57cec5SDimitry Andric getStringLiteral(BoxingMethod->getSelector().getAsString())); 26520b57cec5SDimitry Andric CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 26530b57cec5SDimitry Andric SelExprs, StartLoc, EndLoc); 26540b57cec5SDimitry Andric MsgExprs.push_back(SelExp); 26550b57cec5SDimitry Andric 26560b57cec5SDimitry Andric // User provided sub-expression is the 3rd, and last, argument. 26570b57cec5SDimitry Andric Expr *subExpr = Exp->getSubExpr(); 26580b57cec5SDimitry Andric if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) { 26590b57cec5SDimitry Andric QualType type = ICE->getType(); 26600b57cec5SDimitry Andric const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 26610b57cec5SDimitry Andric CastKind CK = CK_BitCast; 26620b57cec5SDimitry Andric if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType()) 26630b57cec5SDimitry Andric CK = CK_IntegralToBoolean; 26640b57cec5SDimitry Andric subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr); 26650b57cec5SDimitry Andric } 26660b57cec5SDimitry Andric MsgExprs.push_back(subExpr); 26670b57cec5SDimitry Andric 26680b57cec5SDimitry Andric SmallVector<QualType, 4> ArgTypes; 26690b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCClassType()); 26700b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCSelType()); 26710b57cec5SDimitry Andric for (const auto PI : BoxingMethod->parameters()) 26720b57cec5SDimitry Andric ArgTypes.push_back(PI->getType()); 26730b57cec5SDimitry Andric 26740b57cec5SDimitry Andric QualType returnType = Exp->getType(); 26750b57cec5SDimitry Andric // Get the type, we will need to reference it in a couple spots. 26760b57cec5SDimitry Andric QualType msgSendType = MsgSendFlavor->getType(); 26770b57cec5SDimitry Andric 26780b57cec5SDimitry Andric // Create a reference to the objc_msgSend() declaration. 26790b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr( 26800b57cec5SDimitry Andric *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation()); 26810b57cec5SDimitry Andric 26820b57cec5SDimitry Andric CastExpr *cast = NoTypeInfoCStyleCastExpr( 26830b57cec5SDimitry Andric Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE); 26840b57cec5SDimitry Andric 26850b57cec5SDimitry Andric // Now do the "normal" pointer to function cast. 26860b57cec5SDimitry Andric QualType castType = 26870b57cec5SDimitry Andric getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic()); 26880b57cec5SDimitry Andric castType = Context->getPointerType(castType); 26890b57cec5SDimitry Andric cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 26900b57cec5SDimitry Andric cast); 26910b57cec5SDimitry Andric 26920b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 26930b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 26940b57cec5SDimitry Andric 26955ffd83dbSDimitry Andric auto *FT = msgSendType->castAs<FunctionType>(); 26960b57cec5SDimitry Andric CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), 2697fe6060f1SDimitry Andric VK_PRValue, EndLoc, FPOptionsOverride()); 26980b57cec5SDimitry Andric ReplaceStmt(Exp, CE); 26990b57cec5SDimitry Andric return CE; 27000b57cec5SDimitry Andric } 27010b57cec5SDimitry Andric 27020b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { 27030b57cec5SDimitry Andric // synthesize declaration of helper functions needed in this routine. 27040b57cec5SDimitry Andric if (!SelGetUidFunctionDecl) 27050b57cec5SDimitry Andric SynthSelGetUidFunctionDecl(); 27060b57cec5SDimitry Andric // use objc_msgSend() for all. 27070b57cec5SDimitry Andric if (!MsgSendFunctionDecl) 27080b57cec5SDimitry Andric SynthMsgSendFunctionDecl(); 27090b57cec5SDimitry Andric if (!GetClassFunctionDecl) 27100b57cec5SDimitry Andric SynthGetClassFunctionDecl(); 27110b57cec5SDimitry Andric 27120b57cec5SDimitry Andric FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 27130b57cec5SDimitry Andric SourceLocation StartLoc = Exp->getBeginLoc(); 27140b57cec5SDimitry Andric SourceLocation EndLoc = Exp->getEndLoc(); 27150b57cec5SDimitry Andric 27160b57cec5SDimitry Andric // Build the expression: __NSContainer_literal(int, ...).arr 27170b57cec5SDimitry Andric QualType IntQT = Context->IntTy; 27180b57cec5SDimitry Andric QualType NSArrayFType = 27190b57cec5SDimitry Andric getSimpleFunctionType(Context->VoidTy, IntQT, true); 27200b57cec5SDimitry Andric std::string NSArrayFName("__NSContainer_literal"); 27210b57cec5SDimitry Andric FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName); 27220b57cec5SDimitry Andric DeclRefExpr *NSArrayDRE = new (Context) DeclRefExpr( 2723fe6060f1SDimitry Andric *Context, NSArrayFD, false, NSArrayFType, VK_PRValue, SourceLocation()); 27240b57cec5SDimitry Andric 27250b57cec5SDimitry Andric SmallVector<Expr*, 16> InitExprs; 27260b57cec5SDimitry Andric unsigned NumElements = Exp->getNumElements(); 27270b57cec5SDimitry Andric unsigned UnsignedIntSize = 27280b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 27290b57cec5SDimitry Andric Expr *count = IntegerLiteral::Create(*Context, 27300b57cec5SDimitry Andric llvm::APInt(UnsignedIntSize, NumElements), 27310b57cec5SDimitry Andric Context->UnsignedIntTy, SourceLocation()); 27320b57cec5SDimitry Andric InitExprs.push_back(count); 27330b57cec5SDimitry Andric for (unsigned i = 0; i < NumElements; i++) 27340b57cec5SDimitry Andric InitExprs.push_back(Exp->getElement(i)); 27350b57cec5SDimitry Andric Expr *NSArrayCallExpr = 27360b57cec5SDimitry Andric CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue, 2737e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 27380b57cec5SDimitry Andric 27390b57cec5SDimitry Andric FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 27400b57cec5SDimitry Andric SourceLocation(), 27410b57cec5SDimitry Andric &Context->Idents.get("arr"), 27420b57cec5SDimitry Andric Context->getPointerType(Context->VoidPtrTy), 27430b57cec5SDimitry Andric nullptr, /*BitWidth=*/nullptr, 27440b57cec5SDimitry Andric /*Mutable=*/true, ICIS_NoInit); 27450b57cec5SDimitry Andric MemberExpr *ArrayLiteralME = 27460b57cec5SDimitry Andric MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD, 27470b57cec5SDimitry Andric ARRFD->getType(), VK_LValue, OK_Ordinary); 27480b57cec5SDimitry Andric QualType ConstIdT = Context->getObjCIdType().withConst(); 27490b57cec5SDimitry Andric CStyleCastExpr * ArrayLiteralObjects = 27500b57cec5SDimitry Andric NoTypeInfoCStyleCastExpr(Context, 27510b57cec5SDimitry Andric Context->getPointerType(ConstIdT), 27520b57cec5SDimitry Andric CK_BitCast, 27530b57cec5SDimitry Andric ArrayLiteralME); 27540b57cec5SDimitry Andric 27550b57cec5SDimitry Andric // Synthesize a call to objc_msgSend(). 27560b57cec5SDimitry Andric SmallVector<Expr*, 32> MsgExprs; 27570b57cec5SDimitry Andric SmallVector<Expr*, 4> ClsExprs; 27580b57cec5SDimitry Andric QualType expType = Exp->getType(); 27590b57cec5SDimitry Andric 27600b57cec5SDimitry Andric // Create a call to objc_getClass("NSArray"). It will be th 1st argument. 27610b57cec5SDimitry Andric ObjCInterfaceDecl *Class = 2762a7dea167SDimitry Andric expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface(); 27630b57cec5SDimitry Andric 27640b57cec5SDimitry Andric IdentifierInfo *clsName = Class->getIdentifier(); 27650b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(clsName->getName())); 27660b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs, 27670b57cec5SDimitry Andric StartLoc, EndLoc); 27680b57cec5SDimitry Andric MsgExprs.push_back(Cls); 27690b57cec5SDimitry Andric 27700b57cec5SDimitry Andric // Create a call to sel_registerName("arrayWithObjects:count:"). 27710b57cec5SDimitry Andric // it will be the 2nd argument. 27720b57cec5SDimitry Andric SmallVector<Expr*, 4> SelExprs; 27730b57cec5SDimitry Andric ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod(); 27740b57cec5SDimitry Andric SelExprs.push_back( 27750b57cec5SDimitry Andric getStringLiteral(ArrayMethod->getSelector().getAsString())); 27760b57cec5SDimitry Andric CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 27770b57cec5SDimitry Andric SelExprs, StartLoc, EndLoc); 27780b57cec5SDimitry Andric MsgExprs.push_back(SelExp); 27790b57cec5SDimitry Andric 27800b57cec5SDimitry Andric // (const id [])objects 27810b57cec5SDimitry Andric MsgExprs.push_back(ArrayLiteralObjects); 27820b57cec5SDimitry Andric 27830b57cec5SDimitry Andric // (NSUInteger)cnt 27840b57cec5SDimitry Andric Expr *cnt = IntegerLiteral::Create(*Context, 27850b57cec5SDimitry Andric llvm::APInt(UnsignedIntSize, NumElements), 27860b57cec5SDimitry Andric Context->UnsignedIntTy, SourceLocation()); 27870b57cec5SDimitry Andric MsgExprs.push_back(cnt); 27880b57cec5SDimitry Andric 27890b57cec5SDimitry Andric SmallVector<QualType, 4> ArgTypes; 27900b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCClassType()); 27910b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCSelType()); 27920b57cec5SDimitry Andric for (const auto *PI : ArrayMethod->parameters()) 27930b57cec5SDimitry Andric ArgTypes.push_back(PI->getType()); 27940b57cec5SDimitry Andric 27950b57cec5SDimitry Andric QualType returnType = Exp->getType(); 27960b57cec5SDimitry Andric // Get the type, we will need to reference it in a couple spots. 27970b57cec5SDimitry Andric QualType msgSendType = MsgSendFlavor->getType(); 27980b57cec5SDimitry Andric 27990b57cec5SDimitry Andric // Create a reference to the objc_msgSend() declaration. 28000b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr( 28010b57cec5SDimitry Andric *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation()); 28020b57cec5SDimitry Andric 28030b57cec5SDimitry Andric CastExpr *cast = NoTypeInfoCStyleCastExpr( 28040b57cec5SDimitry Andric Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE); 28050b57cec5SDimitry Andric 28060b57cec5SDimitry Andric // Now do the "normal" pointer to function cast. 28070b57cec5SDimitry Andric QualType castType = 28080b57cec5SDimitry Andric getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic()); 28090b57cec5SDimitry Andric castType = Context->getPointerType(castType); 28100b57cec5SDimitry Andric cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 28110b57cec5SDimitry Andric cast); 28120b57cec5SDimitry Andric 28130b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 28140b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 28150b57cec5SDimitry Andric 2816a7dea167SDimitry Andric const FunctionType *FT = msgSendType->castAs<FunctionType>(); 28170b57cec5SDimitry Andric CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), 2818fe6060f1SDimitry Andric VK_PRValue, EndLoc, FPOptionsOverride()); 28190b57cec5SDimitry Andric ReplaceStmt(Exp, CE); 28200b57cec5SDimitry Andric return CE; 28210b57cec5SDimitry Andric } 28220b57cec5SDimitry Andric 28230b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) { 28240b57cec5SDimitry Andric // synthesize declaration of helper functions needed in this routine. 28250b57cec5SDimitry Andric if (!SelGetUidFunctionDecl) 28260b57cec5SDimitry Andric SynthSelGetUidFunctionDecl(); 28270b57cec5SDimitry Andric // use objc_msgSend() for all. 28280b57cec5SDimitry Andric if (!MsgSendFunctionDecl) 28290b57cec5SDimitry Andric SynthMsgSendFunctionDecl(); 28300b57cec5SDimitry Andric if (!GetClassFunctionDecl) 28310b57cec5SDimitry Andric SynthGetClassFunctionDecl(); 28320b57cec5SDimitry Andric 28330b57cec5SDimitry Andric FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 28340b57cec5SDimitry Andric SourceLocation StartLoc = Exp->getBeginLoc(); 28350b57cec5SDimitry Andric SourceLocation EndLoc = Exp->getEndLoc(); 28360b57cec5SDimitry Andric 28370b57cec5SDimitry Andric // Build the expression: __NSContainer_literal(int, ...).arr 28380b57cec5SDimitry Andric QualType IntQT = Context->IntTy; 28390b57cec5SDimitry Andric QualType NSDictFType = 28400b57cec5SDimitry Andric getSimpleFunctionType(Context->VoidTy, IntQT, true); 28410b57cec5SDimitry Andric std::string NSDictFName("__NSContainer_literal"); 28420b57cec5SDimitry Andric FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName); 28430b57cec5SDimitry Andric DeclRefExpr *NSDictDRE = new (Context) DeclRefExpr( 2844fe6060f1SDimitry Andric *Context, NSDictFD, false, NSDictFType, VK_PRValue, SourceLocation()); 28450b57cec5SDimitry Andric 28460b57cec5SDimitry Andric SmallVector<Expr*, 16> KeyExprs; 28470b57cec5SDimitry Andric SmallVector<Expr*, 16> ValueExprs; 28480b57cec5SDimitry Andric 28490b57cec5SDimitry Andric unsigned NumElements = Exp->getNumElements(); 28500b57cec5SDimitry Andric unsigned UnsignedIntSize = 28510b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 28520b57cec5SDimitry Andric Expr *count = IntegerLiteral::Create(*Context, 28530b57cec5SDimitry Andric llvm::APInt(UnsignedIntSize, NumElements), 28540b57cec5SDimitry Andric Context->UnsignedIntTy, SourceLocation()); 28550b57cec5SDimitry Andric KeyExprs.push_back(count); 28560b57cec5SDimitry Andric ValueExprs.push_back(count); 28570b57cec5SDimitry Andric for (unsigned i = 0; i < NumElements; i++) { 28580b57cec5SDimitry Andric ObjCDictionaryElement Element = Exp->getKeyValueElement(i); 28590b57cec5SDimitry Andric KeyExprs.push_back(Element.Key); 28600b57cec5SDimitry Andric ValueExprs.push_back(Element.Value); 28610b57cec5SDimitry Andric } 28620b57cec5SDimitry Andric 28630b57cec5SDimitry Andric // (const id [])objects 28640b57cec5SDimitry Andric Expr *NSValueCallExpr = 28650b57cec5SDimitry Andric CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue, 2866e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 28670b57cec5SDimitry Andric 28680b57cec5SDimitry Andric FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 28690b57cec5SDimitry Andric SourceLocation(), 28700b57cec5SDimitry Andric &Context->Idents.get("arr"), 28710b57cec5SDimitry Andric Context->getPointerType(Context->VoidPtrTy), 28720b57cec5SDimitry Andric nullptr, /*BitWidth=*/nullptr, 28730b57cec5SDimitry Andric /*Mutable=*/true, ICIS_NoInit); 28740b57cec5SDimitry Andric MemberExpr *DictLiteralValueME = 28750b57cec5SDimitry Andric MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD, 28760b57cec5SDimitry Andric ARRFD->getType(), VK_LValue, OK_Ordinary); 28770b57cec5SDimitry Andric QualType ConstIdT = Context->getObjCIdType().withConst(); 28780b57cec5SDimitry Andric CStyleCastExpr * DictValueObjects = 28790b57cec5SDimitry Andric NoTypeInfoCStyleCastExpr(Context, 28800b57cec5SDimitry Andric Context->getPointerType(ConstIdT), 28810b57cec5SDimitry Andric CK_BitCast, 28820b57cec5SDimitry Andric DictLiteralValueME); 28830b57cec5SDimitry Andric // (const id <NSCopying> [])keys 2884e8d8bef9SDimitry Andric Expr *NSKeyCallExpr = 2885e8d8bef9SDimitry Andric CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue, 2886e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 28870b57cec5SDimitry Andric 28880b57cec5SDimitry Andric MemberExpr *DictLiteralKeyME = 28890b57cec5SDimitry Andric MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD, 28900b57cec5SDimitry Andric ARRFD->getType(), VK_LValue, OK_Ordinary); 28910b57cec5SDimitry Andric 28920b57cec5SDimitry Andric CStyleCastExpr * DictKeyObjects = 28930b57cec5SDimitry Andric NoTypeInfoCStyleCastExpr(Context, 28940b57cec5SDimitry Andric Context->getPointerType(ConstIdT), 28950b57cec5SDimitry Andric CK_BitCast, 28960b57cec5SDimitry Andric DictLiteralKeyME); 28970b57cec5SDimitry Andric 28980b57cec5SDimitry Andric // Synthesize a call to objc_msgSend(). 28990b57cec5SDimitry Andric SmallVector<Expr*, 32> MsgExprs; 29000b57cec5SDimitry Andric SmallVector<Expr*, 4> ClsExprs; 29010b57cec5SDimitry Andric QualType expType = Exp->getType(); 29020b57cec5SDimitry Andric 29030b57cec5SDimitry Andric // Create a call to objc_getClass("NSArray"). It will be th 1st argument. 29040b57cec5SDimitry Andric ObjCInterfaceDecl *Class = 2905a7dea167SDimitry Andric expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface(); 29060b57cec5SDimitry Andric 29070b57cec5SDimitry Andric IdentifierInfo *clsName = Class->getIdentifier(); 29080b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(clsName->getName())); 29090b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs, 29100b57cec5SDimitry Andric StartLoc, EndLoc); 29110b57cec5SDimitry Andric MsgExprs.push_back(Cls); 29120b57cec5SDimitry Andric 29130b57cec5SDimitry Andric // Create a call to sel_registerName("arrayWithObjects:count:"). 29140b57cec5SDimitry Andric // it will be the 2nd argument. 29150b57cec5SDimitry Andric SmallVector<Expr*, 4> SelExprs; 29160b57cec5SDimitry Andric ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod(); 29170b57cec5SDimitry Andric SelExprs.push_back(getStringLiteral(DictMethod->getSelector().getAsString())); 29180b57cec5SDimitry Andric CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 29190b57cec5SDimitry Andric SelExprs, StartLoc, EndLoc); 29200b57cec5SDimitry Andric MsgExprs.push_back(SelExp); 29210b57cec5SDimitry Andric 29220b57cec5SDimitry Andric // (const id [])objects 29230b57cec5SDimitry Andric MsgExprs.push_back(DictValueObjects); 29240b57cec5SDimitry Andric 29250b57cec5SDimitry Andric // (const id <NSCopying> [])keys 29260b57cec5SDimitry Andric MsgExprs.push_back(DictKeyObjects); 29270b57cec5SDimitry Andric 29280b57cec5SDimitry Andric // (NSUInteger)cnt 29290b57cec5SDimitry Andric Expr *cnt = IntegerLiteral::Create(*Context, 29300b57cec5SDimitry Andric llvm::APInt(UnsignedIntSize, NumElements), 29310b57cec5SDimitry Andric Context->UnsignedIntTy, SourceLocation()); 29320b57cec5SDimitry Andric MsgExprs.push_back(cnt); 29330b57cec5SDimitry Andric 29340b57cec5SDimitry Andric SmallVector<QualType, 8> ArgTypes; 29350b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCClassType()); 29360b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCSelType()); 29370b57cec5SDimitry Andric for (const auto *PI : DictMethod->parameters()) { 29380b57cec5SDimitry Andric QualType T = PI->getType(); 29390b57cec5SDimitry Andric if (const PointerType* PT = T->getAs<PointerType>()) { 29400b57cec5SDimitry Andric QualType PointeeTy = PT->getPointeeType(); 29410b57cec5SDimitry Andric convertToUnqualifiedObjCType(PointeeTy); 29420b57cec5SDimitry Andric T = Context->getPointerType(PointeeTy); 29430b57cec5SDimitry Andric } 29440b57cec5SDimitry Andric ArgTypes.push_back(T); 29450b57cec5SDimitry Andric } 29460b57cec5SDimitry Andric 29470b57cec5SDimitry Andric QualType returnType = Exp->getType(); 29480b57cec5SDimitry Andric // Get the type, we will need to reference it in a couple spots. 29490b57cec5SDimitry Andric QualType msgSendType = MsgSendFlavor->getType(); 29500b57cec5SDimitry Andric 29510b57cec5SDimitry Andric // Create a reference to the objc_msgSend() declaration. 29520b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr( 29530b57cec5SDimitry Andric *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation()); 29540b57cec5SDimitry Andric 29550b57cec5SDimitry Andric CastExpr *cast = NoTypeInfoCStyleCastExpr( 29560b57cec5SDimitry Andric Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE); 29570b57cec5SDimitry Andric 29580b57cec5SDimitry Andric // Now do the "normal" pointer to function cast. 29590b57cec5SDimitry Andric QualType castType = 29600b57cec5SDimitry Andric getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic()); 29610b57cec5SDimitry Andric castType = Context->getPointerType(castType); 29620b57cec5SDimitry Andric cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 29630b57cec5SDimitry Andric cast); 29640b57cec5SDimitry Andric 29650b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 29660b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 29670b57cec5SDimitry Andric 2968a7dea167SDimitry Andric const FunctionType *FT = msgSendType->castAs<FunctionType>(); 29690b57cec5SDimitry Andric CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), 2970fe6060f1SDimitry Andric VK_PRValue, EndLoc, FPOptionsOverride()); 29710b57cec5SDimitry Andric ReplaceStmt(Exp, CE); 29720b57cec5SDimitry Andric return CE; 29730b57cec5SDimitry Andric } 29740b57cec5SDimitry Andric 29750b57cec5SDimitry Andric // struct __rw_objc_super { 29760b57cec5SDimitry Andric // struct objc_object *object; struct objc_object *superClass; 29770b57cec5SDimitry Andric // }; 29780b57cec5SDimitry Andric QualType RewriteModernObjC::getSuperStructType() { 29790b57cec5SDimitry Andric if (!SuperStructDecl) { 29805f757f3fSDimitry Andric SuperStructDecl = RecordDecl::Create( 29815f757f3fSDimitry Andric *Context, TagTypeKind::Struct, TUDecl, SourceLocation(), 29825f757f3fSDimitry Andric SourceLocation(), &Context->Idents.get("__rw_objc_super")); 29830b57cec5SDimitry Andric QualType FieldTypes[2]; 29840b57cec5SDimitry Andric 29850b57cec5SDimitry Andric // struct objc_object *object; 29860b57cec5SDimitry Andric FieldTypes[0] = Context->getObjCIdType(); 29870b57cec5SDimitry Andric // struct objc_object *superClass; 29880b57cec5SDimitry Andric FieldTypes[1] = Context->getObjCIdType(); 29890b57cec5SDimitry Andric 29900b57cec5SDimitry Andric // Create fields 29910b57cec5SDimitry Andric for (unsigned i = 0; i < 2; ++i) { 29920b57cec5SDimitry Andric SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, 29930b57cec5SDimitry Andric SourceLocation(), 29940b57cec5SDimitry Andric SourceLocation(), nullptr, 29950b57cec5SDimitry Andric FieldTypes[i], nullptr, 29960b57cec5SDimitry Andric /*BitWidth=*/nullptr, 29970b57cec5SDimitry Andric /*Mutable=*/false, 29980b57cec5SDimitry Andric ICIS_NoInit)); 29990b57cec5SDimitry Andric } 30000b57cec5SDimitry Andric 30010b57cec5SDimitry Andric SuperStructDecl->completeDefinition(); 30020b57cec5SDimitry Andric } 30030b57cec5SDimitry Andric return Context->getTagDeclType(SuperStructDecl); 30040b57cec5SDimitry Andric } 30050b57cec5SDimitry Andric 30060b57cec5SDimitry Andric QualType RewriteModernObjC::getConstantStringStructType() { 30070b57cec5SDimitry Andric if (!ConstantStringDecl) { 30085f757f3fSDimitry Andric ConstantStringDecl = RecordDecl::Create( 30095f757f3fSDimitry Andric *Context, TagTypeKind::Struct, TUDecl, SourceLocation(), 30105f757f3fSDimitry Andric SourceLocation(), &Context->Idents.get("__NSConstantStringImpl")); 30110b57cec5SDimitry Andric QualType FieldTypes[4]; 30120b57cec5SDimitry Andric 30130b57cec5SDimitry Andric // struct objc_object *receiver; 30140b57cec5SDimitry Andric FieldTypes[0] = Context->getObjCIdType(); 30150b57cec5SDimitry Andric // int flags; 30160b57cec5SDimitry Andric FieldTypes[1] = Context->IntTy; 30170b57cec5SDimitry Andric // char *str; 30180b57cec5SDimitry Andric FieldTypes[2] = Context->getPointerType(Context->CharTy); 30190b57cec5SDimitry Andric // long length; 30200b57cec5SDimitry Andric FieldTypes[3] = Context->LongTy; 30210b57cec5SDimitry Andric 30220b57cec5SDimitry Andric // Create fields 30230b57cec5SDimitry Andric for (unsigned i = 0; i < 4; ++i) { 30240b57cec5SDimitry Andric ConstantStringDecl->addDecl(FieldDecl::Create(*Context, 30250b57cec5SDimitry Andric ConstantStringDecl, 30260b57cec5SDimitry Andric SourceLocation(), 30270b57cec5SDimitry Andric SourceLocation(), nullptr, 30280b57cec5SDimitry Andric FieldTypes[i], nullptr, 30290b57cec5SDimitry Andric /*BitWidth=*/nullptr, 30300b57cec5SDimitry Andric /*Mutable=*/true, 30310b57cec5SDimitry Andric ICIS_NoInit)); 30320b57cec5SDimitry Andric } 30330b57cec5SDimitry Andric 30340b57cec5SDimitry Andric ConstantStringDecl->completeDefinition(); 30350b57cec5SDimitry Andric } 30360b57cec5SDimitry Andric return Context->getTagDeclType(ConstantStringDecl); 30370b57cec5SDimitry Andric } 30380b57cec5SDimitry Andric 30390b57cec5SDimitry Andric /// getFunctionSourceLocation - returns start location of a function 30400b57cec5SDimitry Andric /// definition. Complication arises when function has declared as 30410b57cec5SDimitry Andric /// extern "C" or extern "C" {...} 30420b57cec5SDimitry Andric static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R, 30430b57cec5SDimitry Andric FunctionDecl *FD) { 30440b57cec5SDimitry Andric if (FD->isExternC() && !FD->isMain()) { 30450b57cec5SDimitry Andric const DeclContext *DC = FD->getDeclContext(); 30460b57cec5SDimitry Andric if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC)) 30470b57cec5SDimitry Andric // if it is extern "C" {...}, return function decl's own location. 30480b57cec5SDimitry Andric if (!LSD->getRBraceLoc().isValid()) 30490b57cec5SDimitry Andric return LSD->getExternLoc(); 30500b57cec5SDimitry Andric } 30510b57cec5SDimitry Andric if (FD->getStorageClass() != SC_None) 30520b57cec5SDimitry Andric R.RewriteBlockLiteralFunctionDecl(FD); 30530b57cec5SDimitry Andric return FD->getTypeSpecStartLoc(); 30540b57cec5SDimitry Andric } 30550b57cec5SDimitry Andric 30560b57cec5SDimitry Andric void RewriteModernObjC::RewriteLineDirective(const Decl *D) { 30570b57cec5SDimitry Andric 30580b57cec5SDimitry Andric SourceLocation Location = D->getLocation(); 30590b57cec5SDimitry Andric 30600b57cec5SDimitry Andric if (Location.isFileID() && GenerateLineInfo) { 30610b57cec5SDimitry Andric std::string LineString("\n#line "); 30620b57cec5SDimitry Andric PresumedLoc PLoc = SM->getPresumedLoc(Location); 30630b57cec5SDimitry Andric LineString += utostr(PLoc.getLine()); 30640b57cec5SDimitry Andric LineString += " \""; 30650b57cec5SDimitry Andric LineString += Lexer::Stringify(PLoc.getFilename()); 30660b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(D)) 30670b57cec5SDimitry Andric LineString += "\""; 30680b57cec5SDimitry Andric else LineString += "\"\n"; 30690b57cec5SDimitry Andric 30700b57cec5SDimitry Andric Location = D->getBeginLoc(); 30710b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 30720b57cec5SDimitry Andric if (FD->isExternC() && !FD->isMain()) { 30730b57cec5SDimitry Andric const DeclContext *DC = FD->getDeclContext(); 30740b57cec5SDimitry Andric if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC)) 30750b57cec5SDimitry Andric // if it is extern "C" {...}, return function decl's own location. 30760b57cec5SDimitry Andric if (!LSD->getRBraceLoc().isValid()) 30770b57cec5SDimitry Andric Location = LSD->getExternLoc(); 30780b57cec5SDimitry Andric } 30790b57cec5SDimitry Andric } 30800b57cec5SDimitry Andric InsertText(Location, LineString); 30810b57cec5SDimitry Andric } 30820b57cec5SDimitry Andric } 30830b57cec5SDimitry Andric 30840b57cec5SDimitry Andric /// SynthMsgSendStretCallExpr - This routine translates message expression 30850b57cec5SDimitry Andric /// into a call to objc_msgSend_stret() entry point. Tricky part is that 30860b57cec5SDimitry Andric /// nil check on receiver must be performed before calling objc_msgSend_stret. 30870b57cec5SDimitry Andric /// MsgSendStretFlavor - function declaration objc_msgSend_stret(...) 30880b57cec5SDimitry Andric /// msgSendType - function type of objc_msgSend_stret(...) 30890b57cec5SDimitry Andric /// returnType - Result type of the method being synthesized. 30900b57cec5SDimitry Andric /// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type. 30910b57cec5SDimitry Andric /// MsgExprs - list of argument expressions being passed to objc_msgSend_stret, 30920b57cec5SDimitry Andric /// starting with receiver. 30930b57cec5SDimitry Andric /// Method - Method being rewritten. 30940b57cec5SDimitry Andric Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, 30950b57cec5SDimitry Andric QualType returnType, 30960b57cec5SDimitry Andric SmallVectorImpl<QualType> &ArgTypes, 30970b57cec5SDimitry Andric SmallVectorImpl<Expr*> &MsgExprs, 30980b57cec5SDimitry Andric ObjCMethodDecl *Method) { 30990b57cec5SDimitry Andric // Now do the "normal" pointer to function cast. 31000b57cec5SDimitry Andric QualType FuncType = getSimpleFunctionType( 31010b57cec5SDimitry Andric returnType, ArgTypes, Method ? Method->isVariadic() : false); 31020b57cec5SDimitry Andric QualType castType = Context->getPointerType(FuncType); 31030b57cec5SDimitry Andric 31040b57cec5SDimitry Andric // build type for containing the objc_msgSend_stret object. 31050b57cec5SDimitry Andric static unsigned stretCount=0; 31060b57cec5SDimitry Andric std::string name = "__Stret"; name += utostr(stretCount); 31070b57cec5SDimitry Andric std::string str = 31080b57cec5SDimitry Andric "extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n"; 31090b57cec5SDimitry Andric str += "namespace {\n"; 31100b57cec5SDimitry Andric str += "struct "; str += name; 31110b57cec5SDimitry Andric str += " {\n\t"; 31120b57cec5SDimitry Andric str += name; 31130b57cec5SDimitry Andric str += "(id receiver, SEL sel"; 31140b57cec5SDimitry Andric for (unsigned i = 2; i < ArgTypes.size(); i++) { 31150b57cec5SDimitry Andric std::string ArgName = "arg"; ArgName += utostr(i); 31160b57cec5SDimitry Andric ArgTypes[i].getAsStringInternal(ArgName, Context->getPrintingPolicy()); 31170b57cec5SDimitry Andric str += ", "; str += ArgName; 31180b57cec5SDimitry Andric } 31190b57cec5SDimitry Andric // could be vararg. 31200b57cec5SDimitry Andric for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) { 31210b57cec5SDimitry Andric std::string ArgName = "arg"; ArgName += utostr(i); 31220b57cec5SDimitry Andric MsgExprs[i]->getType().getAsStringInternal(ArgName, 31230b57cec5SDimitry Andric Context->getPrintingPolicy()); 31240b57cec5SDimitry Andric str += ", "; str += ArgName; 31250b57cec5SDimitry Andric } 31260b57cec5SDimitry Andric 31270b57cec5SDimitry Andric str += ") {\n"; 31280b57cec5SDimitry Andric str += "\t unsigned size = sizeof("; 31290b57cec5SDimitry Andric str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n"; 31300b57cec5SDimitry Andric 31310b57cec5SDimitry Andric str += "\t if (size == 1 || size == 2 || size == 4 || size == 8)\n"; 31320b57cec5SDimitry Andric 31330b57cec5SDimitry Andric str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy()); 31340b57cec5SDimitry Andric str += ")(void *)objc_msgSend)(receiver, sel"; 31350b57cec5SDimitry Andric for (unsigned i = 2; i < ArgTypes.size(); i++) { 31360b57cec5SDimitry Andric str += ", arg"; str += utostr(i); 31370b57cec5SDimitry Andric } 31380b57cec5SDimitry Andric // could be vararg. 31390b57cec5SDimitry Andric for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) { 31400b57cec5SDimitry Andric str += ", arg"; str += utostr(i); 31410b57cec5SDimitry Andric } 31420b57cec5SDimitry Andric str+= ");\n"; 31430b57cec5SDimitry Andric 31440b57cec5SDimitry Andric str += "\t else if (receiver == 0)\n"; 31450b57cec5SDimitry Andric str += "\t memset((void*)&s, 0, sizeof(s));\n"; 31460b57cec5SDimitry Andric str += "\t else\n"; 31470b57cec5SDimitry Andric 31480b57cec5SDimitry Andric str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy()); 31490b57cec5SDimitry Andric str += ")(void *)objc_msgSend_stret)(receiver, sel"; 31500b57cec5SDimitry Andric for (unsigned i = 2; i < ArgTypes.size(); i++) { 31510b57cec5SDimitry Andric str += ", arg"; str += utostr(i); 31520b57cec5SDimitry Andric } 31530b57cec5SDimitry Andric // could be vararg. 31540b57cec5SDimitry Andric for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) { 31550b57cec5SDimitry Andric str += ", arg"; str += utostr(i); 31560b57cec5SDimitry Andric } 31570b57cec5SDimitry Andric str += ");\n"; 31580b57cec5SDimitry Andric 31590b57cec5SDimitry Andric str += "\t}\n"; 31600b57cec5SDimitry Andric str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy()); 31610b57cec5SDimitry Andric str += " s;\n"; 31620b57cec5SDimitry Andric str += "};\n};\n\n"; 31630b57cec5SDimitry Andric SourceLocation FunLocStart; 31640b57cec5SDimitry Andric if (CurFunctionDef) 31650b57cec5SDimitry Andric FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef); 31660b57cec5SDimitry Andric else { 31670b57cec5SDimitry Andric assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null"); 31680b57cec5SDimitry Andric FunLocStart = CurMethodDef->getBeginLoc(); 31690b57cec5SDimitry Andric } 31700b57cec5SDimitry Andric 31710b57cec5SDimitry Andric InsertText(FunLocStart, str); 31720b57cec5SDimitry Andric ++stretCount; 31730b57cec5SDimitry Andric 31740b57cec5SDimitry Andric // AST for __Stretn(receiver, args).s; 31750b57cec5SDimitry Andric IdentifierInfo *ID = &Context->Idents.get(name); 31760b57cec5SDimitry Andric FunctionDecl *FD = 31770b57cec5SDimitry Andric FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), 31780b57cec5SDimitry Andric ID, FuncType, nullptr, SC_Extern, false, false); 31790b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 3180fe6060f1SDimitry Andric DeclRefExpr(*Context, FD, false, castType, VK_PRValue, SourceLocation()); 3181e8d8bef9SDimitry Andric CallExpr *STCE = 3182e8d8bef9SDimitry Andric CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue, 3183e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 31840b57cec5SDimitry Andric 31850b57cec5SDimitry Andric FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 31860b57cec5SDimitry Andric SourceLocation(), 31870b57cec5SDimitry Andric &Context->Idents.get("s"), 31880b57cec5SDimitry Andric returnType, nullptr, 31890b57cec5SDimitry Andric /*BitWidth=*/nullptr, 31900b57cec5SDimitry Andric /*Mutable=*/true, ICIS_NoInit); 31910b57cec5SDimitry Andric MemberExpr *ME = MemberExpr::CreateImplicit( 31920b57cec5SDimitry Andric *Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary); 31930b57cec5SDimitry Andric 31940b57cec5SDimitry Andric return ME; 31950b57cec5SDimitry Andric } 31960b57cec5SDimitry Andric 31970b57cec5SDimitry Andric Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 31980b57cec5SDimitry Andric SourceLocation StartLoc, 31990b57cec5SDimitry Andric SourceLocation EndLoc) { 32000b57cec5SDimitry Andric if (!SelGetUidFunctionDecl) 32010b57cec5SDimitry Andric SynthSelGetUidFunctionDecl(); 32020b57cec5SDimitry Andric if (!MsgSendFunctionDecl) 32030b57cec5SDimitry Andric SynthMsgSendFunctionDecl(); 32040b57cec5SDimitry Andric if (!MsgSendSuperFunctionDecl) 32050b57cec5SDimitry Andric SynthMsgSendSuperFunctionDecl(); 32060b57cec5SDimitry Andric if (!MsgSendStretFunctionDecl) 32070b57cec5SDimitry Andric SynthMsgSendStretFunctionDecl(); 32080b57cec5SDimitry Andric if (!MsgSendSuperStretFunctionDecl) 32090b57cec5SDimitry Andric SynthMsgSendSuperStretFunctionDecl(); 32100b57cec5SDimitry Andric if (!MsgSendFpretFunctionDecl) 32110b57cec5SDimitry Andric SynthMsgSendFpretFunctionDecl(); 32120b57cec5SDimitry Andric if (!GetClassFunctionDecl) 32130b57cec5SDimitry Andric SynthGetClassFunctionDecl(); 32140b57cec5SDimitry Andric if (!GetSuperClassFunctionDecl) 32150b57cec5SDimitry Andric SynthGetSuperClassFunctionDecl(); 32160b57cec5SDimitry Andric if (!GetMetaClassFunctionDecl) 32170b57cec5SDimitry Andric SynthGetMetaClassFunctionDecl(); 32180b57cec5SDimitry Andric 32190b57cec5SDimitry Andric // default to objc_msgSend(). 32200b57cec5SDimitry Andric FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 32210b57cec5SDimitry Andric // May need to use objc_msgSend_stret() as well. 32220b57cec5SDimitry Andric FunctionDecl *MsgSendStretFlavor = nullptr; 32230b57cec5SDimitry Andric if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { 32240b57cec5SDimitry Andric QualType resultType = mDecl->getReturnType(); 32250b57cec5SDimitry Andric if (resultType->isRecordType()) 32260b57cec5SDimitry Andric MsgSendStretFlavor = MsgSendStretFunctionDecl; 32270b57cec5SDimitry Andric else if (resultType->isRealFloatingType()) 32280b57cec5SDimitry Andric MsgSendFlavor = MsgSendFpretFunctionDecl; 32290b57cec5SDimitry Andric } 32300b57cec5SDimitry Andric 32310b57cec5SDimitry Andric // Synthesize a call to objc_msgSend(). 32320b57cec5SDimitry Andric SmallVector<Expr*, 8> MsgExprs; 32330b57cec5SDimitry Andric switch (Exp->getReceiverKind()) { 32340b57cec5SDimitry Andric case ObjCMessageExpr::SuperClass: { 32350b57cec5SDimitry Andric MsgSendFlavor = MsgSendSuperFunctionDecl; 32360b57cec5SDimitry Andric if (MsgSendStretFlavor) 32370b57cec5SDimitry Andric MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 32380b57cec5SDimitry Andric assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 32390b57cec5SDimitry Andric 32400b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 32410b57cec5SDimitry Andric 32420b57cec5SDimitry Andric SmallVector<Expr*, 4> InitExprs; 32430b57cec5SDimitry Andric 32440b57cec5SDimitry Andric // set the receiver to self, the first argument to all methods. 3245fe6060f1SDimitry Andric InitExprs.push_back(NoTypeInfoCStyleCastExpr( 3246fe6060f1SDimitry Andric Context, Context->getObjCIdType(), CK_BitCast, 3247fe6060f1SDimitry Andric new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false, 3248fe6060f1SDimitry Andric Context->getObjCIdType(), VK_PRValue, 3249fe6060f1SDimitry Andric SourceLocation()))); // set the 'receiver'. 32500b57cec5SDimitry Andric 32510b57cec5SDimitry Andric // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 32520b57cec5SDimitry Andric SmallVector<Expr*, 8> ClsExprs; 32530b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName())); 32540b57cec5SDimitry Andric // (Class)objc_getClass("CurrentClass") 32550b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, 32560b57cec5SDimitry Andric ClsExprs, StartLoc, EndLoc); 32570b57cec5SDimitry Andric ClsExprs.clear(); 32580b57cec5SDimitry Andric ClsExprs.push_back(Cls); 32590b57cec5SDimitry Andric Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs, 32600b57cec5SDimitry Andric StartLoc, EndLoc); 32610b57cec5SDimitry Andric 32620b57cec5SDimitry Andric // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 32630b57cec5SDimitry Andric // To turn off a warning, type-cast to 'id' 32640b57cec5SDimitry Andric InitExprs.push_back( // set 'super class', using class_getSuperclass(). 32650b57cec5SDimitry Andric NoTypeInfoCStyleCastExpr(Context, 32660b57cec5SDimitry Andric Context->getObjCIdType(), 32670b57cec5SDimitry Andric CK_BitCast, Cls)); 32680b57cec5SDimitry Andric // struct __rw_objc_super 32690b57cec5SDimitry Andric QualType superType = getSuperStructType(); 32700b57cec5SDimitry Andric Expr *SuperRep; 32710b57cec5SDimitry Andric 32720b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 32730b57cec5SDimitry Andric SynthSuperConstructorFunctionDecl(); 32740b57cec5SDimitry Andric // Simulate a constructor call... 32750b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 32760b57cec5SDimitry Andric DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, 32770b57cec5SDimitry Andric VK_LValue, SourceLocation()); 3278e8d8bef9SDimitry Andric SuperRep = 3279e8d8bef9SDimitry Andric CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue, 3280e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 32810b57cec5SDimitry Andric // The code for super is a little tricky to prevent collision with 32820b57cec5SDimitry Andric // the structure definition in the header. The rewriter has it's own 32830b57cec5SDimitry Andric // internal definition (__rw_objc_super) that is uses. This is why 32840b57cec5SDimitry Andric // we need the cast below. For example: 32850b57cec5SDimitry Andric // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 32860b57cec5SDimitry Andric // 32875ffd83dbSDimitry Andric SuperRep = UnaryOperator::Create( 32885ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf, 3289fe6060f1SDimitry Andric Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary, 32905ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 32910b57cec5SDimitry Andric SuperRep = NoTypeInfoCStyleCastExpr(Context, 32920b57cec5SDimitry Andric Context->getPointerType(superType), 32930b57cec5SDimitry Andric CK_BitCast, SuperRep); 32940b57cec5SDimitry Andric } else { 32950b57cec5SDimitry Andric // (struct __rw_objc_super) { <exprs from above> } 32960b57cec5SDimitry Andric InitListExpr *ILE = 32970b57cec5SDimitry Andric new (Context) InitListExpr(*Context, SourceLocation(), InitExprs, 32980b57cec5SDimitry Andric SourceLocation()); 32990b57cec5SDimitry Andric TypeSourceInfo *superTInfo 33000b57cec5SDimitry Andric = Context->getTrivialTypeSourceInfo(superType); 33010b57cec5SDimitry Andric SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 33020b57cec5SDimitry Andric superType, VK_LValue, 33030b57cec5SDimitry Andric ILE, false); 33040b57cec5SDimitry Andric // struct __rw_objc_super * 33055ffd83dbSDimitry Andric SuperRep = UnaryOperator::Create( 33065ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf, 3307fe6060f1SDimitry Andric Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary, 33085ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 33090b57cec5SDimitry Andric } 33100b57cec5SDimitry Andric MsgExprs.push_back(SuperRep); 33110b57cec5SDimitry Andric break; 33120b57cec5SDimitry Andric } 33130b57cec5SDimitry Andric 33140b57cec5SDimitry Andric case ObjCMessageExpr::Class: { 33150b57cec5SDimitry Andric SmallVector<Expr*, 8> ClsExprs; 33160b57cec5SDimitry Andric ObjCInterfaceDecl *Class 3317a7dea167SDimitry Andric = Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface(); 33180b57cec5SDimitry Andric IdentifierInfo *clsName = Class->getIdentifier(); 33190b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(clsName->getName())); 33200b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs, 33210b57cec5SDimitry Andric StartLoc, EndLoc); 33220b57cec5SDimitry Andric CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 33230b57cec5SDimitry Andric Context->getObjCIdType(), 33240b57cec5SDimitry Andric CK_BitCast, Cls); 33250b57cec5SDimitry Andric MsgExprs.push_back(ArgExpr); 33260b57cec5SDimitry Andric break; 33270b57cec5SDimitry Andric } 33280b57cec5SDimitry Andric 33290b57cec5SDimitry Andric case ObjCMessageExpr::SuperInstance:{ 33300b57cec5SDimitry Andric MsgSendFlavor = MsgSendSuperFunctionDecl; 33310b57cec5SDimitry Andric if (MsgSendStretFlavor) 33320b57cec5SDimitry Andric MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 33330b57cec5SDimitry Andric assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 33340b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 33350b57cec5SDimitry Andric SmallVector<Expr*, 4> InitExprs; 33360b57cec5SDimitry Andric 3337fe6060f1SDimitry Andric InitExprs.push_back(NoTypeInfoCStyleCastExpr( 3338fe6060f1SDimitry Andric Context, Context->getObjCIdType(), CK_BitCast, 3339fe6060f1SDimitry Andric new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false, 3340fe6060f1SDimitry Andric Context->getObjCIdType(), VK_PRValue, 3341fe6060f1SDimitry Andric SourceLocation()))); // set the 'receiver'. 33420b57cec5SDimitry Andric 33430b57cec5SDimitry Andric // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 33440b57cec5SDimitry Andric SmallVector<Expr*, 8> ClsExprs; 33450b57cec5SDimitry Andric ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName())); 33460b57cec5SDimitry Andric // (Class)objc_getClass("CurrentClass") 33470b57cec5SDimitry Andric CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs, 33480b57cec5SDimitry Andric StartLoc, EndLoc); 33490b57cec5SDimitry Andric ClsExprs.clear(); 33500b57cec5SDimitry Andric ClsExprs.push_back(Cls); 33510b57cec5SDimitry Andric Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs, 33520b57cec5SDimitry Andric StartLoc, EndLoc); 33530b57cec5SDimitry Andric 33540b57cec5SDimitry Andric // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 33550b57cec5SDimitry Andric // To turn off a warning, type-cast to 'id' 33560b57cec5SDimitry Andric InitExprs.push_back( 33570b57cec5SDimitry Andric // set 'super class', using class_getSuperclass(). 33580b57cec5SDimitry Andric NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 33590b57cec5SDimitry Andric CK_BitCast, Cls)); 33600b57cec5SDimitry Andric // struct __rw_objc_super 33610b57cec5SDimitry Andric QualType superType = getSuperStructType(); 33620b57cec5SDimitry Andric Expr *SuperRep; 33630b57cec5SDimitry Andric 33640b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 33650b57cec5SDimitry Andric SynthSuperConstructorFunctionDecl(); 33660b57cec5SDimitry Andric // Simulate a constructor call... 33670b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 33680b57cec5SDimitry Andric DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType, 33690b57cec5SDimitry Andric VK_LValue, SourceLocation()); 3370e8d8bef9SDimitry Andric SuperRep = 3371e8d8bef9SDimitry Andric CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue, 3372e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 33730b57cec5SDimitry Andric // The code for super is a little tricky to prevent collision with 33740b57cec5SDimitry Andric // the structure definition in the header. The rewriter has it's own 33750b57cec5SDimitry Andric // internal definition (__rw_objc_super) that is uses. This is why 33760b57cec5SDimitry Andric // we need the cast below. For example: 33770b57cec5SDimitry Andric // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 33780b57cec5SDimitry Andric // 33795ffd83dbSDimitry Andric SuperRep = UnaryOperator::Create( 33805ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf, 3381fe6060f1SDimitry Andric Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary, 33825ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 33830b57cec5SDimitry Andric SuperRep = NoTypeInfoCStyleCastExpr(Context, 33840b57cec5SDimitry Andric Context->getPointerType(superType), 33850b57cec5SDimitry Andric CK_BitCast, SuperRep); 33860b57cec5SDimitry Andric } else { 33870b57cec5SDimitry Andric // (struct __rw_objc_super) { <exprs from above> } 33880b57cec5SDimitry Andric InitListExpr *ILE = 33890b57cec5SDimitry Andric new (Context) InitListExpr(*Context, SourceLocation(), InitExprs, 33900b57cec5SDimitry Andric SourceLocation()); 33910b57cec5SDimitry Andric TypeSourceInfo *superTInfo 33920b57cec5SDimitry Andric = Context->getTrivialTypeSourceInfo(superType); 3393fe6060f1SDimitry Andric SuperRep = new (Context) CompoundLiteralExpr( 3394fe6060f1SDimitry Andric SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false); 33950b57cec5SDimitry Andric } 33960b57cec5SDimitry Andric MsgExprs.push_back(SuperRep); 33970b57cec5SDimitry Andric break; 33980b57cec5SDimitry Andric } 33990b57cec5SDimitry Andric 34000b57cec5SDimitry Andric case ObjCMessageExpr::Instance: { 34010b57cec5SDimitry Andric // Remove all type-casts because it may contain objc-style types; e.g. 34020b57cec5SDimitry Andric // Foo<Proto> *. 34030b57cec5SDimitry Andric Expr *recExpr = Exp->getInstanceReceiver(); 34040b57cec5SDimitry Andric while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) 34050b57cec5SDimitry Andric recExpr = CE->getSubExpr(); 34060b57cec5SDimitry Andric CastKind CK = recExpr->getType()->isObjCObjectPointerType() 34070b57cec5SDimitry Andric ? CK_BitCast : recExpr->getType()->isBlockPointerType() 34080b57cec5SDimitry Andric ? CK_BlockPointerToObjCPointerCast 34090b57cec5SDimitry Andric : CK_CPointerToObjCPointerCast; 34100b57cec5SDimitry Andric 34110b57cec5SDimitry Andric recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 34120b57cec5SDimitry Andric CK, recExpr); 34130b57cec5SDimitry Andric MsgExprs.push_back(recExpr); 34140b57cec5SDimitry Andric break; 34150b57cec5SDimitry Andric } 34160b57cec5SDimitry Andric } 34170b57cec5SDimitry Andric 34180b57cec5SDimitry Andric // Create a call to sel_registerName("selName"), it will be the 2nd argument. 34190b57cec5SDimitry Andric SmallVector<Expr*, 8> SelExprs; 34200b57cec5SDimitry Andric SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString())); 34210b57cec5SDimitry Andric CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 34220b57cec5SDimitry Andric SelExprs, StartLoc, EndLoc); 34230b57cec5SDimitry Andric MsgExprs.push_back(SelExp); 34240b57cec5SDimitry Andric 34250b57cec5SDimitry Andric // Now push any user supplied arguments. 34260b57cec5SDimitry Andric for (unsigned i = 0; i < Exp->getNumArgs(); i++) { 34270b57cec5SDimitry Andric Expr *userExpr = Exp->getArg(i); 34280b57cec5SDimitry Andric // Make all implicit casts explicit...ICE comes in handy:-) 34290b57cec5SDimitry Andric if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { 34300b57cec5SDimitry Andric // Reuse the ICE type, it is exactly what the doctor ordered. 34310b57cec5SDimitry Andric QualType type = ICE->getType(); 34320b57cec5SDimitry Andric if (needToScanForQualifiers(type)) 34330b57cec5SDimitry Andric type = Context->getObjCIdType(); 34340b57cec5SDimitry Andric // Make sure we convert "type (^)(...)" to "type (*)(...)". 34350b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(type); 34360b57cec5SDimitry Andric const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 34370b57cec5SDimitry Andric CastKind CK; 34380b57cec5SDimitry Andric if (SubExpr->getType()->isIntegralType(*Context) && 34390b57cec5SDimitry Andric type->isBooleanType()) { 34400b57cec5SDimitry Andric CK = CK_IntegralToBoolean; 34410b57cec5SDimitry Andric } else if (type->isObjCObjectPointerType()) { 34420b57cec5SDimitry Andric if (SubExpr->getType()->isBlockPointerType()) { 34430b57cec5SDimitry Andric CK = CK_BlockPointerToObjCPointerCast; 34440b57cec5SDimitry Andric } else if (SubExpr->getType()->isPointerType()) { 34450b57cec5SDimitry Andric CK = CK_CPointerToObjCPointerCast; 34460b57cec5SDimitry Andric } else { 34470b57cec5SDimitry Andric CK = CK_BitCast; 34480b57cec5SDimitry Andric } 34490b57cec5SDimitry Andric } else { 34500b57cec5SDimitry Andric CK = CK_BitCast; 34510b57cec5SDimitry Andric } 34520b57cec5SDimitry Andric 34530b57cec5SDimitry Andric userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); 34540b57cec5SDimitry Andric } 34550b57cec5SDimitry Andric // Make id<P...> cast into an 'id' cast. 34560b57cec5SDimitry Andric else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { 34570b57cec5SDimitry Andric if (CE->getType()->isObjCQualifiedIdType()) { 34580b57cec5SDimitry Andric while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) 34590b57cec5SDimitry Andric userExpr = CE->getSubExpr(); 34600b57cec5SDimitry Andric CastKind CK; 34610b57cec5SDimitry Andric if (userExpr->getType()->isIntegralType(*Context)) { 34620b57cec5SDimitry Andric CK = CK_IntegralToPointer; 34630b57cec5SDimitry Andric } else if (userExpr->getType()->isBlockPointerType()) { 34640b57cec5SDimitry Andric CK = CK_BlockPointerToObjCPointerCast; 34650b57cec5SDimitry Andric } else if (userExpr->getType()->isPointerType()) { 34660b57cec5SDimitry Andric CK = CK_CPointerToObjCPointerCast; 34670b57cec5SDimitry Andric } else { 34680b57cec5SDimitry Andric CK = CK_BitCast; 34690b57cec5SDimitry Andric } 34700b57cec5SDimitry Andric userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 34710b57cec5SDimitry Andric CK, userExpr); 34720b57cec5SDimitry Andric } 34730b57cec5SDimitry Andric } 34740b57cec5SDimitry Andric MsgExprs.push_back(userExpr); 34750b57cec5SDimitry Andric // We've transferred the ownership to MsgExprs. For now, we *don't* null 34760b57cec5SDimitry Andric // out the argument in the original expression (since we aren't deleting 34770b57cec5SDimitry Andric // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info. 34780b57cec5SDimitry Andric //Exp->setArg(i, 0); 34790b57cec5SDimitry Andric } 34800b57cec5SDimitry Andric // Generate the funky cast. 34810b57cec5SDimitry Andric CastExpr *cast; 34820b57cec5SDimitry Andric SmallVector<QualType, 8> ArgTypes; 34830b57cec5SDimitry Andric QualType returnType; 34840b57cec5SDimitry Andric 34850b57cec5SDimitry Andric // Push 'id' and 'SEL', the 2 implicit arguments. 34860b57cec5SDimitry Andric if (MsgSendFlavor == MsgSendSuperFunctionDecl) 34870b57cec5SDimitry Andric ArgTypes.push_back(Context->getPointerType(getSuperStructType())); 34880b57cec5SDimitry Andric else 34890b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCIdType()); 34900b57cec5SDimitry Andric ArgTypes.push_back(Context->getObjCSelType()); 34910b57cec5SDimitry Andric if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { 34920b57cec5SDimitry Andric // Push any user argument types. 34930b57cec5SDimitry Andric for (const auto *PI : OMD->parameters()) { 34940b57cec5SDimitry Andric QualType t = PI->getType()->isObjCQualifiedIdType() 34950b57cec5SDimitry Andric ? Context->getObjCIdType() 34960b57cec5SDimitry Andric : PI->getType(); 34970b57cec5SDimitry Andric // Make sure we convert "t (^)(...)" to "t (*)(...)". 34980b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(t); 34990b57cec5SDimitry Andric ArgTypes.push_back(t); 35000b57cec5SDimitry Andric } 35010b57cec5SDimitry Andric returnType = Exp->getType(); 35020b57cec5SDimitry Andric convertToUnqualifiedObjCType(returnType); 35030b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(returnType); 35040b57cec5SDimitry Andric } else { 35050b57cec5SDimitry Andric returnType = Context->getObjCIdType(); 35060b57cec5SDimitry Andric } 35070b57cec5SDimitry Andric // Get the type, we will need to reference it in a couple spots. 35080b57cec5SDimitry Andric QualType msgSendType = MsgSendFlavor->getType(); 35090b57cec5SDimitry Andric 35100b57cec5SDimitry Andric // Create a reference to the objc_msgSend() declaration. 35110b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr( 35120b57cec5SDimitry Andric *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation()); 35130b57cec5SDimitry Andric 35140b57cec5SDimitry Andric // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 35150b57cec5SDimitry Andric // If we don't do this cast, we get the following bizarre warning/note: 35160b57cec5SDimitry Andric // xx.m:13: warning: function called through a non-compatible type 35170b57cec5SDimitry Andric // xx.m:13: note: if this code is reached, the program will abort 35180b57cec5SDimitry Andric cast = NoTypeInfoCStyleCastExpr(Context, 35190b57cec5SDimitry Andric Context->getPointerType(Context->VoidTy), 35200b57cec5SDimitry Andric CK_BitCast, DRE); 35210b57cec5SDimitry Andric 35220b57cec5SDimitry Andric // Now do the "normal" pointer to function cast. 35230b57cec5SDimitry Andric // If we don't have a method decl, force a variadic cast. 35240b57cec5SDimitry Andric const ObjCMethodDecl *MD = Exp->getMethodDecl(); 35250b57cec5SDimitry Andric QualType castType = 35260b57cec5SDimitry Andric getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true); 35270b57cec5SDimitry Andric castType = Context->getPointerType(castType); 35280b57cec5SDimitry Andric cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 35290b57cec5SDimitry Andric cast); 35300b57cec5SDimitry Andric 35310b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 35320b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 35330b57cec5SDimitry Andric 3534a7dea167SDimitry Andric const FunctionType *FT = msgSendType->castAs<FunctionType>(); 35350b57cec5SDimitry Andric CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), 3536fe6060f1SDimitry Andric VK_PRValue, EndLoc, FPOptionsOverride()); 35370b57cec5SDimitry Andric Stmt *ReplacingStmt = CE; 35380b57cec5SDimitry Andric if (MsgSendStretFlavor) { 35390b57cec5SDimitry Andric // We have the method which returns a struct/union. Must also generate 35400b57cec5SDimitry Andric // call to objc_msgSend_stret and hang both varieties on a conditional 35410b57cec5SDimitry Andric // expression which dictate which one to envoke depending on size of 35420b57cec5SDimitry Andric // method's return type. 35430b57cec5SDimitry Andric 35440b57cec5SDimitry Andric Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor, 35450b57cec5SDimitry Andric returnType, 35460b57cec5SDimitry Andric ArgTypes, MsgExprs, 35470b57cec5SDimitry Andric Exp->getMethodDecl()); 35480b57cec5SDimitry Andric ReplacingStmt = STCE; 35490b57cec5SDimitry Andric } 35500b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 35510b57cec5SDimitry Andric return ReplacingStmt; 35520b57cec5SDimitry Andric } 35530b57cec5SDimitry Andric 35540b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { 35550b57cec5SDimitry Andric Stmt *ReplacingStmt = 35560b57cec5SDimitry Andric SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc()); 35570b57cec5SDimitry Andric 35580b57cec5SDimitry Andric // Now do the actual rewrite. 35590b57cec5SDimitry Andric ReplaceStmt(Exp, ReplacingStmt); 35600b57cec5SDimitry Andric 35610b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 35620b57cec5SDimitry Andric return ReplacingStmt; 35630b57cec5SDimitry Andric } 35640b57cec5SDimitry Andric 35650b57cec5SDimitry Andric // typedef struct objc_object Protocol; 35660b57cec5SDimitry Andric QualType RewriteModernObjC::getProtocolType() { 35670b57cec5SDimitry Andric if (!ProtocolTypeDecl) { 35680b57cec5SDimitry Andric TypeSourceInfo *TInfo 35690b57cec5SDimitry Andric = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); 35700b57cec5SDimitry Andric ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, 35710b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 35720b57cec5SDimitry Andric &Context->Idents.get("Protocol"), 35730b57cec5SDimitry Andric TInfo); 35740b57cec5SDimitry Andric } 35750b57cec5SDimitry Andric return Context->getTypeDeclType(ProtocolTypeDecl); 35760b57cec5SDimitry Andric } 35770b57cec5SDimitry Andric 35780b57cec5SDimitry Andric /// RewriteObjCProtocolExpr - Rewrite a protocol expression into 35790b57cec5SDimitry Andric /// a synthesized/forward data reference (to the protocol's metadata). 35800b57cec5SDimitry Andric /// The forward references (and metadata) are generated in 35810b57cec5SDimitry Andric /// RewriteModernObjC::HandleTranslationUnit(). 35820b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { 35830b57cec5SDimitry Andric std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" + 35840b57cec5SDimitry Andric Exp->getProtocol()->getNameAsString(); 35850b57cec5SDimitry Andric IdentifierInfo *ID = &Context->Idents.get(Name); 35860b57cec5SDimitry Andric VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 35870b57cec5SDimitry Andric SourceLocation(), ID, getProtocolType(), 35880b57cec5SDimitry Andric nullptr, SC_Extern); 35890b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) DeclRefExpr( 35900b57cec5SDimitry Andric *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation()); 35910b57cec5SDimitry Andric CastExpr *castExpr = NoTypeInfoCStyleCastExpr( 35920b57cec5SDimitry Andric Context, Context->getPointerType(DRE->getType()), CK_BitCast, DRE); 35930b57cec5SDimitry Andric ReplaceStmt(Exp, castExpr); 35940b57cec5SDimitry Andric ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl()); 35950b57cec5SDimitry Andric // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 35960b57cec5SDimitry Andric return castExpr; 35970b57cec5SDimitry Andric } 35980b57cec5SDimitry Andric 35990b57cec5SDimitry Andric /// IsTagDefinedInsideClass - This routine checks that a named tagged type 36000b57cec5SDimitry Andric /// is defined inside an objective-c class. If so, it returns true. 36010b57cec5SDimitry Andric bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, 36020b57cec5SDimitry Andric TagDecl *Tag, 36030b57cec5SDimitry Andric bool &IsNamedDefinition) { 36040b57cec5SDimitry Andric if (!IDecl) 36050b57cec5SDimitry Andric return false; 36060b57cec5SDimitry Andric SourceLocation TagLocation; 36070b57cec5SDimitry Andric if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) { 36080b57cec5SDimitry Andric RD = RD->getDefinition(); 36090b57cec5SDimitry Andric if (!RD || !RD->getDeclName().getAsIdentifierInfo()) 36100b57cec5SDimitry Andric return false; 36110b57cec5SDimitry Andric IsNamedDefinition = true; 36120b57cec5SDimitry Andric TagLocation = RD->getLocation(); 36130b57cec5SDimitry Andric return Context->getSourceManager().isBeforeInTranslationUnit( 36140b57cec5SDimitry Andric IDecl->getLocation(), TagLocation); 36150b57cec5SDimitry Andric } 36160b57cec5SDimitry Andric if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) { 36170b57cec5SDimitry Andric if (!ED || !ED->getDeclName().getAsIdentifierInfo()) 36180b57cec5SDimitry Andric return false; 36190b57cec5SDimitry Andric IsNamedDefinition = true; 36200b57cec5SDimitry Andric TagLocation = ED->getLocation(); 36210b57cec5SDimitry Andric return Context->getSourceManager().isBeforeInTranslationUnit( 36220b57cec5SDimitry Andric IDecl->getLocation(), TagLocation); 36230b57cec5SDimitry Andric } 36240b57cec5SDimitry Andric return false; 36250b57cec5SDimitry Andric } 36260b57cec5SDimitry Andric 36270b57cec5SDimitry Andric /// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer. 36280b57cec5SDimitry Andric /// It handles elaborated types, as well as enum types in the process. 36290b57cec5SDimitry Andric bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type, 36300b57cec5SDimitry Andric std::string &Result) { 3631bdd1243dSDimitry Andric if (Type->getAs<TypedefType>()) { 36320b57cec5SDimitry Andric Result += "\t"; 36330b57cec5SDimitry Andric return false; 36340b57cec5SDimitry Andric } 36350b57cec5SDimitry Andric 36360b57cec5SDimitry Andric if (Type->isArrayType()) { 36370b57cec5SDimitry Andric QualType ElemTy = Context->getBaseElementType(Type); 36380b57cec5SDimitry Andric return RewriteObjCFieldDeclType(ElemTy, Result); 36390b57cec5SDimitry Andric } 36400b57cec5SDimitry Andric else if (Type->isRecordType()) { 3641a7dea167SDimitry Andric RecordDecl *RD = Type->castAs<RecordType>()->getDecl(); 36420b57cec5SDimitry Andric if (RD->isCompleteDefinition()) { 36430b57cec5SDimitry Andric if (RD->isStruct()) 36440b57cec5SDimitry Andric Result += "\n\tstruct "; 36450b57cec5SDimitry Andric else if (RD->isUnion()) 36460b57cec5SDimitry Andric Result += "\n\tunion "; 36470b57cec5SDimitry Andric else 36480b57cec5SDimitry Andric assert(false && "class not allowed as an ivar type"); 36490b57cec5SDimitry Andric 36500b57cec5SDimitry Andric Result += RD->getName(); 36510b57cec5SDimitry Andric if (GlobalDefinedTags.count(RD)) { 36520b57cec5SDimitry Andric // struct/union is defined globally, use it. 36530b57cec5SDimitry Andric Result += " "; 36540b57cec5SDimitry Andric return true; 36550b57cec5SDimitry Andric } 36560b57cec5SDimitry Andric Result += " {\n"; 36570b57cec5SDimitry Andric for (auto *FD : RD->fields()) 36580b57cec5SDimitry Andric RewriteObjCFieldDecl(FD, Result); 36590b57cec5SDimitry Andric Result += "\t} "; 36600b57cec5SDimitry Andric return true; 36610b57cec5SDimitry Andric } 36620b57cec5SDimitry Andric } 36630b57cec5SDimitry Andric else if (Type->isEnumeralType()) { 3664a7dea167SDimitry Andric EnumDecl *ED = Type->castAs<EnumType>()->getDecl(); 36650b57cec5SDimitry Andric if (ED->isCompleteDefinition()) { 36660b57cec5SDimitry Andric Result += "\n\tenum "; 36670b57cec5SDimitry Andric Result += ED->getName(); 36680b57cec5SDimitry Andric if (GlobalDefinedTags.count(ED)) { 36690b57cec5SDimitry Andric // Enum is globall defined, use it. 36700b57cec5SDimitry Andric Result += " "; 36710b57cec5SDimitry Andric return true; 36720b57cec5SDimitry Andric } 36730b57cec5SDimitry Andric 36740b57cec5SDimitry Andric Result += " {\n"; 36750b57cec5SDimitry Andric for (const auto *EC : ED->enumerators()) { 36760b57cec5SDimitry Andric Result += "\t"; Result += EC->getName(); Result += " = "; 3677fe6060f1SDimitry Andric Result += toString(EC->getInitVal(), 10); 36780b57cec5SDimitry Andric Result += ",\n"; 36790b57cec5SDimitry Andric } 36800b57cec5SDimitry Andric Result += "\t} "; 36810b57cec5SDimitry Andric return true; 36820b57cec5SDimitry Andric } 36830b57cec5SDimitry Andric } 36840b57cec5SDimitry Andric 36850b57cec5SDimitry Andric Result += "\t"; 36860b57cec5SDimitry Andric convertObjCTypeToCStyleType(Type); 36870b57cec5SDimitry Andric return false; 36880b57cec5SDimitry Andric } 36890b57cec5SDimitry Andric 36900b57cec5SDimitry Andric 36910b57cec5SDimitry Andric /// RewriteObjCFieldDecl - This routine rewrites a field into the buffer. 36920b57cec5SDimitry Andric /// It handles elaborated types, as well as enum types in the process. 36930b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, 36940b57cec5SDimitry Andric std::string &Result) { 36950b57cec5SDimitry Andric QualType Type = fieldDecl->getType(); 36960b57cec5SDimitry Andric std::string Name = fieldDecl->getNameAsString(); 36970b57cec5SDimitry Andric 36980b57cec5SDimitry Andric bool EleboratedType = RewriteObjCFieldDeclType(Type, Result); 36990b57cec5SDimitry Andric if (!EleboratedType) 37000b57cec5SDimitry Andric Type.getAsStringInternal(Name, Context->getPrintingPolicy()); 37010b57cec5SDimitry Andric Result += Name; 37020b57cec5SDimitry Andric if (fieldDecl->isBitField()) { 37030b57cec5SDimitry Andric Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context)); 37040b57cec5SDimitry Andric } 37050b57cec5SDimitry Andric else if (EleboratedType && Type->isArrayType()) { 37060b57cec5SDimitry Andric const ArrayType *AT = Context->getAsArrayType(Type); 37070b57cec5SDimitry Andric do { 37080b57cec5SDimitry Andric if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 37090b57cec5SDimitry Andric Result += "["; 37100b57cec5SDimitry Andric llvm::APInt Dim = CAT->getSize(); 37110b57cec5SDimitry Andric Result += utostr(Dim.getZExtValue()); 37120b57cec5SDimitry Andric Result += "]"; 37130b57cec5SDimitry Andric } 37140b57cec5SDimitry Andric AT = Context->getAsArrayType(AT->getElementType()); 37150b57cec5SDimitry Andric } while (AT); 37160b57cec5SDimitry Andric } 37170b57cec5SDimitry Andric 37180b57cec5SDimitry Andric Result += ";\n"; 37190b57cec5SDimitry Andric } 37200b57cec5SDimitry Andric 37210b57cec5SDimitry Andric /// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined 37220b57cec5SDimitry Andric /// named aggregate types into the input buffer. 37230b57cec5SDimitry Andric void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl, 37240b57cec5SDimitry Andric std::string &Result) { 37250b57cec5SDimitry Andric QualType Type = fieldDecl->getType(); 3726bdd1243dSDimitry Andric if (Type->getAs<TypedefType>()) 37270b57cec5SDimitry Andric return; 37280b57cec5SDimitry Andric if (Type->isArrayType()) 37290b57cec5SDimitry Andric Type = Context->getBaseElementType(Type); 3730a7dea167SDimitry Andric 3731a7dea167SDimitry Andric auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext()); 37320b57cec5SDimitry Andric 37330b57cec5SDimitry Andric TagDecl *TD = nullptr; 37340b57cec5SDimitry Andric if (Type->isRecordType()) { 3735a7dea167SDimitry Andric TD = Type->castAs<RecordType>()->getDecl(); 37360b57cec5SDimitry Andric } 37370b57cec5SDimitry Andric else if (Type->isEnumeralType()) { 3738a7dea167SDimitry Andric TD = Type->castAs<EnumType>()->getDecl(); 37390b57cec5SDimitry Andric } 37400b57cec5SDimitry Andric 37410b57cec5SDimitry Andric if (TD) { 37420b57cec5SDimitry Andric if (GlobalDefinedTags.count(TD)) 37430b57cec5SDimitry Andric return; 37440b57cec5SDimitry Andric 37450b57cec5SDimitry Andric bool IsNamedDefinition = false; 37460b57cec5SDimitry Andric if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) { 37470b57cec5SDimitry Andric RewriteObjCFieldDeclType(Type, Result); 37480b57cec5SDimitry Andric Result += ";"; 37490b57cec5SDimitry Andric } 37500b57cec5SDimitry Andric if (IsNamedDefinition) 37510b57cec5SDimitry Andric GlobalDefinedTags.insert(TD); 37520b57cec5SDimitry Andric } 37530b57cec5SDimitry Andric } 37540b57cec5SDimitry Andric 37550b57cec5SDimitry Andric unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) { 37560b57cec5SDimitry Andric const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); 37570b57cec5SDimitry Andric if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) { 37580b57cec5SDimitry Andric return IvarGroupNumber[IV]; 37590b57cec5SDimitry Andric } 37600b57cec5SDimitry Andric unsigned GroupNo = 0; 37610b57cec5SDimitry Andric SmallVector<const ObjCIvarDecl *, 8> IVars; 37620b57cec5SDimitry Andric for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 37630b57cec5SDimitry Andric IVD; IVD = IVD->getNextIvar()) 37640b57cec5SDimitry Andric IVars.push_back(IVD); 37650b57cec5SDimitry Andric 37660b57cec5SDimitry Andric for (unsigned i = 0, e = IVars.size(); i < e; i++) 37670b57cec5SDimitry Andric if (IVars[i]->isBitField()) { 37680b57cec5SDimitry Andric IvarGroupNumber[IVars[i++]] = ++GroupNo; 37690b57cec5SDimitry Andric while (i < e && IVars[i]->isBitField()) 37700b57cec5SDimitry Andric IvarGroupNumber[IVars[i++]] = GroupNo; 37710b57cec5SDimitry Andric if (i < e) 37720b57cec5SDimitry Andric --i; 37730b57cec5SDimitry Andric } 37740b57cec5SDimitry Andric 37750b57cec5SDimitry Andric ObjCInterefaceHasBitfieldGroups.insert(CDecl); 37760b57cec5SDimitry Andric return IvarGroupNumber[IV]; 37770b57cec5SDimitry Andric } 37780b57cec5SDimitry Andric 37790b57cec5SDimitry Andric QualType RewriteModernObjC::SynthesizeBitfieldGroupStructType( 37800b57cec5SDimitry Andric ObjCIvarDecl *IV, 37810b57cec5SDimitry Andric SmallVectorImpl<ObjCIvarDecl *> &IVars) { 37820b57cec5SDimitry Andric std::string StructTagName; 37830b57cec5SDimitry Andric ObjCIvarBitfieldGroupType(IV, StructTagName); 37845f757f3fSDimitry Andric RecordDecl *RD = RecordDecl::Create( 37855f757f3fSDimitry Andric *Context, TagTypeKind::Struct, Context->getTranslationUnitDecl(), 37865f757f3fSDimitry Andric SourceLocation(), SourceLocation(), &Context->Idents.get(StructTagName)); 37870b57cec5SDimitry Andric for (unsigned i=0, e = IVars.size(); i < e; i++) { 37880b57cec5SDimitry Andric ObjCIvarDecl *Ivar = IVars[i]; 37890b57cec5SDimitry Andric RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(), 37900b57cec5SDimitry Andric &Context->Idents.get(Ivar->getName()), 37910b57cec5SDimitry Andric Ivar->getType(), 37920b57cec5SDimitry Andric nullptr, /*Expr *BW */Ivar->getBitWidth(), 37930b57cec5SDimitry Andric false, ICIS_NoInit)); 37940b57cec5SDimitry Andric } 37950b57cec5SDimitry Andric RD->completeDefinition(); 37960b57cec5SDimitry Andric return Context->getTagDeclType(RD); 37970b57cec5SDimitry Andric } 37980b57cec5SDimitry Andric 37990b57cec5SDimitry Andric QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) { 38000b57cec5SDimitry Andric const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); 38010b57cec5SDimitry Andric unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); 38020b57cec5SDimitry Andric std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo); 38030b57cec5SDimitry Andric if (GroupRecordType.count(tuple)) 38040b57cec5SDimitry Andric return GroupRecordType[tuple]; 38050b57cec5SDimitry Andric 38060b57cec5SDimitry Andric SmallVector<ObjCIvarDecl *, 8> IVars; 38070b57cec5SDimitry Andric for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 38080b57cec5SDimitry Andric IVD; IVD = IVD->getNextIvar()) { 38090b57cec5SDimitry Andric if (IVD->isBitField()) 38100b57cec5SDimitry Andric IVars.push_back(const_cast<ObjCIvarDecl *>(IVD)); 38110b57cec5SDimitry Andric else { 38120b57cec5SDimitry Andric if (!IVars.empty()) { 38130b57cec5SDimitry Andric unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]); 38140b57cec5SDimitry Andric // Generate the struct type for this group of bitfield ivars. 38150b57cec5SDimitry Andric GroupRecordType[std::make_pair(CDecl, GroupNo)] = 38160b57cec5SDimitry Andric SynthesizeBitfieldGroupStructType(IVars[0], IVars); 38170b57cec5SDimitry Andric IVars.clear(); 38180b57cec5SDimitry Andric } 38190b57cec5SDimitry Andric } 38200b57cec5SDimitry Andric } 38210b57cec5SDimitry Andric if (!IVars.empty()) { 38220b57cec5SDimitry Andric // Do the last one. 38230b57cec5SDimitry Andric unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]); 38240b57cec5SDimitry Andric GroupRecordType[std::make_pair(CDecl, GroupNo)] = 38250b57cec5SDimitry Andric SynthesizeBitfieldGroupStructType(IVars[0], IVars); 38260b57cec5SDimitry Andric } 38270b57cec5SDimitry Andric QualType RetQT = GroupRecordType[tuple]; 38280b57cec5SDimitry Andric assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL"); 38290b57cec5SDimitry Andric 38300b57cec5SDimitry Andric return RetQT; 38310b57cec5SDimitry Andric } 38320b57cec5SDimitry Andric 38330b57cec5SDimitry Andric /// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group. 38340b57cec5SDimitry Andric /// Name would be: classname__GRBF_n where n is the group number for this ivar. 38350b57cec5SDimitry Andric void RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, 38360b57cec5SDimitry Andric std::string &Result) { 38370b57cec5SDimitry Andric const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); 38380b57cec5SDimitry Andric Result += CDecl->getName(); 38390b57cec5SDimitry Andric Result += "__GRBF_"; 38400b57cec5SDimitry Andric unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); 38410b57cec5SDimitry Andric Result += utostr(GroupNo); 38420b57cec5SDimitry Andric } 38430b57cec5SDimitry Andric 38440b57cec5SDimitry Andric /// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group. 38450b57cec5SDimitry Andric /// Name of the struct would be: classname__T_n where n is the group number for 38460b57cec5SDimitry Andric /// this ivar. 38470b57cec5SDimitry Andric void RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, 38480b57cec5SDimitry Andric std::string &Result) { 38490b57cec5SDimitry Andric const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); 38500b57cec5SDimitry Andric Result += CDecl->getName(); 38510b57cec5SDimitry Andric Result += "__T_"; 38520b57cec5SDimitry Andric unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); 38530b57cec5SDimitry Andric Result += utostr(GroupNo); 38540b57cec5SDimitry Andric } 38550b57cec5SDimitry Andric 38560b57cec5SDimitry Andric /// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset. 38570b57cec5SDimitry Andric /// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for 38580b57cec5SDimitry Andric /// this ivar. 38590b57cec5SDimitry Andric void RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, 38600b57cec5SDimitry Andric std::string &Result) { 38610b57cec5SDimitry Andric Result += "OBJC_IVAR_$_"; 38620b57cec5SDimitry Andric ObjCIvarBitfieldGroupDecl(IV, Result); 38630b57cec5SDimitry Andric } 38640b57cec5SDimitry Andric 38650b57cec5SDimitry Andric #define SKIP_BITFIELDS(IX, ENDIX, VEC) { \ 38660b57cec5SDimitry Andric while ((IX < ENDIX) && VEC[IX]->isBitField()) \ 38670b57cec5SDimitry Andric ++IX; \ 38680b57cec5SDimitry Andric if (IX < ENDIX) \ 38690b57cec5SDimitry Andric --IX; \ 38700b57cec5SDimitry Andric } 38710b57cec5SDimitry Andric 38720b57cec5SDimitry Andric /// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to 38730b57cec5SDimitry Andric /// an objective-c class with ivars. 38740b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 38750b57cec5SDimitry Andric std::string &Result) { 38760b57cec5SDimitry Andric assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); 38770b57cec5SDimitry Andric assert(CDecl->getName() != "" && 38780b57cec5SDimitry Andric "Name missing in SynthesizeObjCInternalStruct"); 38790b57cec5SDimitry Andric ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); 38800b57cec5SDimitry Andric SmallVector<ObjCIvarDecl *, 8> IVars; 38810b57cec5SDimitry Andric for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 38820b57cec5SDimitry Andric IVD; IVD = IVD->getNextIvar()) 38830b57cec5SDimitry Andric IVars.push_back(IVD); 38840b57cec5SDimitry Andric 38850b57cec5SDimitry Andric SourceLocation LocStart = CDecl->getBeginLoc(); 38860b57cec5SDimitry Andric SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc(); 38870b57cec5SDimitry Andric 38880b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 38890b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 38900b57cec5SDimitry Andric 38910b57cec5SDimitry Andric // If no ivars and no root or if its root, directly or indirectly, 38920b57cec5SDimitry Andric // have no ivars (thus not synthesized) then no need to synthesize this class. 38930b57cec5SDimitry Andric if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) && 38940b57cec5SDimitry Andric (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { 38950b57cec5SDimitry Andric endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 38960b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf, Result); 38970b57cec5SDimitry Andric return; 38980b57cec5SDimitry Andric } 38990b57cec5SDimitry Andric 39000b57cec5SDimitry Andric // Insert named struct/union definitions inside class to 39010b57cec5SDimitry Andric // outer scope. This follows semantics of locally defined 39020b57cec5SDimitry Andric // struct/unions in objective-c classes. 39030b57cec5SDimitry Andric for (unsigned i = 0, e = IVars.size(); i < e; i++) 39040b57cec5SDimitry Andric RewriteLocallyDefinedNamedAggregates(IVars[i], Result); 39050b57cec5SDimitry Andric 39060b57cec5SDimitry Andric // Insert named structs which are syntheized to group ivar bitfields 39070b57cec5SDimitry Andric // to outer scope as well. 39080b57cec5SDimitry Andric for (unsigned i = 0, e = IVars.size(); i < e; i++) 39090b57cec5SDimitry Andric if (IVars[i]->isBitField()) { 39100b57cec5SDimitry Andric ObjCIvarDecl *IV = IVars[i]; 39110b57cec5SDimitry Andric QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV); 39120b57cec5SDimitry Andric RewriteObjCFieldDeclType(QT, Result); 39130b57cec5SDimitry Andric Result += ";"; 39140b57cec5SDimitry Andric // skip over ivar bitfields in this group. 39150b57cec5SDimitry Andric SKIP_BITFIELDS(i , e, IVars); 39160b57cec5SDimitry Andric } 39170b57cec5SDimitry Andric 39180b57cec5SDimitry Andric Result += "\nstruct "; 39190b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 39200b57cec5SDimitry Andric Result += "_IMPL {\n"; 39210b57cec5SDimitry Andric 39220b57cec5SDimitry Andric if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 39230b57cec5SDimitry Andric Result += "\tstruct "; Result += RCDecl->getNameAsString(); 39240b57cec5SDimitry Andric Result += "_IMPL "; Result += RCDecl->getNameAsString(); 39250b57cec5SDimitry Andric Result += "_IVARS;\n"; 39260b57cec5SDimitry Andric } 39270b57cec5SDimitry Andric 39280b57cec5SDimitry Andric for (unsigned i = 0, e = IVars.size(); i < e; i++) { 39290b57cec5SDimitry Andric if (IVars[i]->isBitField()) { 39300b57cec5SDimitry Andric ObjCIvarDecl *IV = IVars[i]; 39310b57cec5SDimitry Andric Result += "\tstruct "; 39320b57cec5SDimitry Andric ObjCIvarBitfieldGroupType(IV, Result); Result += " "; 39330b57cec5SDimitry Andric ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n"; 39340b57cec5SDimitry Andric // skip over ivar bitfields in this group. 39350b57cec5SDimitry Andric SKIP_BITFIELDS(i , e, IVars); 39360b57cec5SDimitry Andric } 39370b57cec5SDimitry Andric else 39380b57cec5SDimitry Andric RewriteObjCFieldDecl(IVars[i], Result); 39390b57cec5SDimitry Andric } 39400b57cec5SDimitry Andric 39410b57cec5SDimitry Andric Result += "};\n"; 39420b57cec5SDimitry Andric endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 39430b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf, Result); 39440b57cec5SDimitry Andric // Mark this struct as having been generated. 39450b57cec5SDimitry Andric if (!ObjCSynthesizedStructs.insert(CDecl).second) 39460b57cec5SDimitry Andric llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct"); 39470b57cec5SDimitry Andric } 39480b57cec5SDimitry Andric 39490b57cec5SDimitry Andric /// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which 39500b57cec5SDimitry Andric /// have been referenced in an ivar access expression. 39510b57cec5SDimitry Andric void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, 39520b57cec5SDimitry Andric std::string &Result) { 39530b57cec5SDimitry Andric // write out ivar offset symbols which have been referenced in an ivar 39540b57cec5SDimitry Andric // access expression. 39550b57cec5SDimitry Andric llvm::SmallSetVector<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl]; 39560b57cec5SDimitry Andric 39570b57cec5SDimitry Andric if (Ivars.empty()) 39580b57cec5SDimitry Andric return; 39590b57cec5SDimitry Andric 39600b57cec5SDimitry Andric llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput; 39610b57cec5SDimitry Andric for (ObjCIvarDecl *IvarDecl : Ivars) { 39620b57cec5SDimitry Andric const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface(); 39630b57cec5SDimitry Andric unsigned GroupNo = 0; 39640b57cec5SDimitry Andric if (IvarDecl->isBitField()) { 39650b57cec5SDimitry Andric GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl); 39660b57cec5SDimitry Andric if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo))) 39670b57cec5SDimitry Andric continue; 39680b57cec5SDimitry Andric } 39690b57cec5SDimitry Andric Result += "\n"; 39700b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 39710b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_ivar$B\")) "; 39720b57cec5SDimitry Andric Result += "extern \"C\" "; 39730b57cec5SDimitry Andric if (LangOpts.MicrosoftExt && 39740b57cec5SDimitry Andric IvarDecl->getAccessControl() != ObjCIvarDecl::Private && 39750b57cec5SDimitry Andric IvarDecl->getAccessControl() != ObjCIvarDecl::Package) 39760b57cec5SDimitry Andric Result += "__declspec(dllimport) "; 39770b57cec5SDimitry Andric 39780b57cec5SDimitry Andric Result += "unsigned long "; 39790b57cec5SDimitry Andric if (IvarDecl->isBitField()) { 39800b57cec5SDimitry Andric ObjCIvarBitfieldGroupOffset(IvarDecl, Result); 39810b57cec5SDimitry Andric GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo)); 39820b57cec5SDimitry Andric } 39830b57cec5SDimitry Andric else 39840b57cec5SDimitry Andric WriteInternalIvarName(CDecl, IvarDecl, Result); 39850b57cec5SDimitry Andric Result += ";"; 39860b57cec5SDimitry Andric } 39870b57cec5SDimitry Andric } 39880b57cec5SDimitry Andric 39890b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 39900b57cec5SDimitry Andric // Meta Data Emission 39910b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 39920b57cec5SDimitry Andric 39930b57cec5SDimitry Andric /// RewriteImplementations - This routine rewrites all method implementations 39940b57cec5SDimitry Andric /// and emits meta-data. 39950b57cec5SDimitry Andric 39960b57cec5SDimitry Andric void RewriteModernObjC::RewriteImplementations() { 39970b57cec5SDimitry Andric int ClsDefCount = ClassImplementation.size(); 39980b57cec5SDimitry Andric int CatDefCount = CategoryImplementation.size(); 39990b57cec5SDimitry Andric 40000b57cec5SDimitry Andric // Rewrite implemented methods 40010b57cec5SDimitry Andric for (int i = 0; i < ClsDefCount; i++) { 40020b57cec5SDimitry Andric ObjCImplementationDecl *OIMP = ClassImplementation[i]; 40030b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl = OIMP->getClassInterface(); 40040b57cec5SDimitry Andric if (CDecl->isImplicitInterfaceDecl()) 40050b57cec5SDimitry Andric assert(false && 40060b57cec5SDimitry Andric "Legacy implicit interface rewriting not supported in moder abi"); 40070b57cec5SDimitry Andric RewriteImplementationDecl(OIMP); 40080b57cec5SDimitry Andric } 40090b57cec5SDimitry Andric 40100b57cec5SDimitry Andric for (int i = 0; i < CatDefCount; i++) { 40110b57cec5SDimitry Andric ObjCCategoryImplDecl *CIMP = CategoryImplementation[i]; 40120b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl = CIMP->getClassInterface(); 40130b57cec5SDimitry Andric if (CDecl->isImplicitInterfaceDecl()) 40140b57cec5SDimitry Andric assert(false && 40150b57cec5SDimitry Andric "Legacy implicit interface rewriting not supported in moder abi"); 40160b57cec5SDimitry Andric RewriteImplementationDecl(CIMP); 40170b57cec5SDimitry Andric } 40180b57cec5SDimitry Andric } 40190b57cec5SDimitry Andric 40200b57cec5SDimitry Andric void RewriteModernObjC::RewriteByRefString(std::string &ResultStr, 40210b57cec5SDimitry Andric const std::string &Name, 40220b57cec5SDimitry Andric ValueDecl *VD, bool def) { 40230b57cec5SDimitry Andric assert(BlockByRefDeclNo.count(VD) && 40240b57cec5SDimitry Andric "RewriteByRefString: ByRef decl missing"); 40250b57cec5SDimitry Andric if (def) 40260b57cec5SDimitry Andric ResultStr += "struct "; 40270b57cec5SDimitry Andric ResultStr += "__Block_byref_" + Name + 40280b57cec5SDimitry Andric "_" + utostr(BlockByRefDeclNo[VD]) ; 40290b57cec5SDimitry Andric } 40300b57cec5SDimitry Andric 40310b57cec5SDimitry Andric static bool HasLocalVariableExternalStorage(ValueDecl *VD) { 40320b57cec5SDimitry Andric if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 40330b57cec5SDimitry Andric return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage()); 40340b57cec5SDimitry Andric return false; 40350b57cec5SDimitry Andric } 40360b57cec5SDimitry Andric 40370b57cec5SDimitry Andric std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, 40380b57cec5SDimitry Andric StringRef funcName, 4039*0fca6ea1SDimitry Andric const std::string &Tag) { 40400b57cec5SDimitry Andric const FunctionType *AFT = CE->getFunctionType(); 40410b57cec5SDimitry Andric QualType RT = AFT->getReturnType(); 40420b57cec5SDimitry Andric std::string StructRef = "struct " + Tag; 40430b57cec5SDimitry Andric SourceLocation BlockLoc = CE->getExprLoc(); 40440b57cec5SDimitry Andric std::string S; 40450b57cec5SDimitry Andric ConvertSourceLocationToLineDirective(BlockLoc, S); 40460b57cec5SDimitry Andric 40470b57cec5SDimitry Andric S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" + 40480b57cec5SDimitry Andric funcName.str() + "_block_func_" + utostr(i); 40490b57cec5SDimitry Andric 40500b57cec5SDimitry Andric BlockDecl *BD = CE->getBlockDecl(); 40510b57cec5SDimitry Andric 40520b57cec5SDimitry Andric if (isa<FunctionNoProtoType>(AFT)) { 40530b57cec5SDimitry Andric // No user-supplied arguments. Still need to pass in a pointer to the 40540b57cec5SDimitry Andric // block (to reference imported block decl refs). 40550b57cec5SDimitry Andric S += "(" + StructRef + " *__cself)"; 40560b57cec5SDimitry Andric } else if (BD->param_empty()) { 40570b57cec5SDimitry Andric S += "(" + StructRef + " *__cself)"; 40580b57cec5SDimitry Andric } else { 40590b57cec5SDimitry Andric const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); 40600b57cec5SDimitry Andric assert(FT && "SynthesizeBlockFunc: No function proto"); 40610b57cec5SDimitry Andric S += '('; 40620b57cec5SDimitry Andric // first add the implicit argument. 40630b57cec5SDimitry Andric S += StructRef + " *__cself, "; 40640b57cec5SDimitry Andric std::string ParamStr; 40650b57cec5SDimitry Andric for (BlockDecl::param_iterator AI = BD->param_begin(), 40660b57cec5SDimitry Andric E = BD->param_end(); AI != E; ++AI) { 40670b57cec5SDimitry Andric if (AI != BD->param_begin()) S += ", "; 40680b57cec5SDimitry Andric ParamStr = (*AI)->getNameAsString(); 40690b57cec5SDimitry Andric QualType QT = (*AI)->getType(); 40700b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(QT); 40710b57cec5SDimitry Andric QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); 40720b57cec5SDimitry Andric S += ParamStr; 40730b57cec5SDimitry Andric } 40740b57cec5SDimitry Andric if (FT->isVariadic()) { 40750b57cec5SDimitry Andric if (!BD->param_empty()) S += ", "; 40760b57cec5SDimitry Andric S += "..."; 40770b57cec5SDimitry Andric } 40780b57cec5SDimitry Andric S += ')'; 40790b57cec5SDimitry Andric } 40800b57cec5SDimitry Andric S += " {\n"; 40810b57cec5SDimitry Andric 40820b57cec5SDimitry Andric // Create local declarations to avoid rewriting all closure decl ref exprs. 40830b57cec5SDimitry Andric // First, emit a declaration for all "by ref" decls. 40840b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 40850b57cec5SDimitry Andric E = BlockByRefDecls.end(); I != E; ++I) { 40860b57cec5SDimitry Andric S += " "; 40870b57cec5SDimitry Andric std::string Name = (*I)->getNameAsString(); 40880b57cec5SDimitry Andric std::string TypeString; 40890b57cec5SDimitry Andric RewriteByRefString(TypeString, Name, (*I)); 40900b57cec5SDimitry Andric TypeString += " *"; 40910b57cec5SDimitry Andric Name = TypeString + Name; 40920b57cec5SDimitry Andric S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; 40930b57cec5SDimitry Andric } 40940b57cec5SDimitry Andric // Next, emit a declaration for all "by copy" declarations. 40950b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 40960b57cec5SDimitry Andric E = BlockByCopyDecls.end(); I != E; ++I) { 40970b57cec5SDimitry Andric S += " "; 40980b57cec5SDimitry Andric // Handle nested closure invocation. For example: 40990b57cec5SDimitry Andric // 41000b57cec5SDimitry Andric // void (^myImportedClosure)(void); 41010b57cec5SDimitry Andric // myImportedClosure = ^(void) { setGlobalInt(x + y); }; 41020b57cec5SDimitry Andric // 41030b57cec5SDimitry Andric // void (^anotherClosure)(void); 41040b57cec5SDimitry Andric // anotherClosure = ^(void) { 41050b57cec5SDimitry Andric // myImportedClosure(); // import and invoke the closure 41060b57cec5SDimitry Andric // }; 41070b57cec5SDimitry Andric // 41080b57cec5SDimitry Andric if (isTopLevelBlockPointerType((*I)->getType())) { 41090b57cec5SDimitry Andric RewriteBlockPointerTypeVariable(S, (*I)); 41100b57cec5SDimitry Andric S += " = ("; 41110b57cec5SDimitry Andric RewriteBlockPointerType(S, (*I)->getType()); 41120b57cec5SDimitry Andric S += ")"; 41130b57cec5SDimitry Andric S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n"; 41140b57cec5SDimitry Andric } 41150b57cec5SDimitry Andric else { 41160b57cec5SDimitry Andric std::string Name = (*I)->getNameAsString(); 41170b57cec5SDimitry Andric QualType QT = (*I)->getType(); 41180b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(*I)) 41190b57cec5SDimitry Andric QT = Context->getPointerType(QT); 41200b57cec5SDimitry Andric QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 41210b57cec5SDimitry Andric S += Name + " = __cself->" + 41220b57cec5SDimitry Andric (*I)->getNameAsString() + "; // bound by copy\n"; 41230b57cec5SDimitry Andric } 41240b57cec5SDimitry Andric } 41250b57cec5SDimitry Andric std::string RewrittenStr = RewrittenBlockExprs[CE]; 41260b57cec5SDimitry Andric const char *cstr = RewrittenStr.c_str(); 41270b57cec5SDimitry Andric while (*cstr++ != '{') ; 41280b57cec5SDimitry Andric S += cstr; 41290b57cec5SDimitry Andric S += "\n"; 41300b57cec5SDimitry Andric return S; 41310b57cec5SDimitry Andric } 41320b57cec5SDimitry Andric 4133*0fca6ea1SDimitry Andric std::string RewriteModernObjC::SynthesizeBlockHelperFuncs( 4134*0fca6ea1SDimitry Andric BlockExpr *CE, int i, StringRef funcName, const std::string &Tag) { 41350b57cec5SDimitry Andric std::string StructRef = "struct " + Tag; 41360b57cec5SDimitry Andric std::string S = "static void __"; 41370b57cec5SDimitry Andric 41380b57cec5SDimitry Andric S += funcName; 41390b57cec5SDimitry Andric S += "_block_copy_" + utostr(i); 41400b57cec5SDimitry Andric S += "(" + StructRef; 41410b57cec5SDimitry Andric S += "*dst, " + StructRef; 41420b57cec5SDimitry Andric S += "*src) {"; 41430b57cec5SDimitry Andric for (ValueDecl *VD : ImportedBlockDecls) { 41440b57cec5SDimitry Andric S += "_Block_object_assign((void*)&dst->"; 41450b57cec5SDimitry Andric S += VD->getNameAsString(); 41460b57cec5SDimitry Andric S += ", (void*)src->"; 41470b57cec5SDimitry Andric S += VD->getNameAsString(); 41480b57cec5SDimitry Andric if (BlockByRefDeclsPtrSet.count(VD)) 41490b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 41500b57cec5SDimitry Andric else if (VD->getType()->isBlockPointerType()) 41510b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 41520b57cec5SDimitry Andric else 41530b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 41540b57cec5SDimitry Andric } 41550b57cec5SDimitry Andric S += "}\n"; 41560b57cec5SDimitry Andric 41570b57cec5SDimitry Andric S += "\nstatic void __"; 41580b57cec5SDimitry Andric S += funcName; 41590b57cec5SDimitry Andric S += "_block_dispose_" + utostr(i); 41600b57cec5SDimitry Andric S += "(" + StructRef; 41610b57cec5SDimitry Andric S += "*src) {"; 41620b57cec5SDimitry Andric for (ValueDecl *VD : ImportedBlockDecls) { 41630b57cec5SDimitry Andric S += "_Block_object_dispose((void*)src->"; 41640b57cec5SDimitry Andric S += VD->getNameAsString(); 41650b57cec5SDimitry Andric if (BlockByRefDeclsPtrSet.count(VD)) 41660b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 41670b57cec5SDimitry Andric else if (VD->getType()->isBlockPointerType()) 41680b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 41690b57cec5SDimitry Andric else 41700b57cec5SDimitry Andric S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 41710b57cec5SDimitry Andric } 41720b57cec5SDimitry Andric S += "}\n"; 41730b57cec5SDimitry Andric return S; 41740b57cec5SDimitry Andric } 41750b57cec5SDimitry Andric 4176*0fca6ea1SDimitry Andric std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, 4177*0fca6ea1SDimitry Andric const std::string &Tag, 4178*0fca6ea1SDimitry Andric const std::string &Desc) { 41790b57cec5SDimitry Andric std::string S = "\nstruct " + Tag; 41800b57cec5SDimitry Andric std::string Constructor = " " + Tag; 41810b57cec5SDimitry Andric 41820b57cec5SDimitry Andric S += " {\n struct __block_impl impl;\n"; 41830b57cec5SDimitry Andric S += " struct " + Desc; 41840b57cec5SDimitry Andric S += "* Desc;\n"; 41850b57cec5SDimitry Andric 41860b57cec5SDimitry Andric Constructor += "(void *fp, "; // Invoke function pointer. 41870b57cec5SDimitry Andric Constructor += "struct " + Desc; // Descriptor pointer. 41880b57cec5SDimitry Andric Constructor += " *desc"; 41890b57cec5SDimitry Andric 41900b57cec5SDimitry Andric if (BlockDeclRefs.size()) { 41910b57cec5SDimitry Andric // Output all "by copy" declarations. 41920b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 41930b57cec5SDimitry Andric E = BlockByCopyDecls.end(); I != E; ++I) { 41940b57cec5SDimitry Andric S += " "; 41950b57cec5SDimitry Andric std::string FieldName = (*I)->getNameAsString(); 41960b57cec5SDimitry Andric std::string ArgName = "_" + FieldName; 41970b57cec5SDimitry Andric // Handle nested closure invocation. For example: 41980b57cec5SDimitry Andric // 41990b57cec5SDimitry Andric // void (^myImportedBlock)(void); 42000b57cec5SDimitry Andric // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 42010b57cec5SDimitry Andric // 42020b57cec5SDimitry Andric // void (^anotherBlock)(void); 42030b57cec5SDimitry Andric // anotherBlock = ^(void) { 42040b57cec5SDimitry Andric // myImportedBlock(); // import and invoke the closure 42050b57cec5SDimitry Andric // }; 42060b57cec5SDimitry Andric // 42070b57cec5SDimitry Andric if (isTopLevelBlockPointerType((*I)->getType())) { 42080b57cec5SDimitry Andric S += "struct __block_impl *"; 42090b57cec5SDimitry Andric Constructor += ", void *" + ArgName; 42100b57cec5SDimitry Andric } else { 42110b57cec5SDimitry Andric QualType QT = (*I)->getType(); 42120b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(*I)) 42130b57cec5SDimitry Andric QT = Context->getPointerType(QT); 42140b57cec5SDimitry Andric QT.getAsStringInternal(FieldName, Context->getPrintingPolicy()); 42150b57cec5SDimitry Andric QT.getAsStringInternal(ArgName, Context->getPrintingPolicy()); 42160b57cec5SDimitry Andric Constructor += ", " + ArgName; 42170b57cec5SDimitry Andric } 42180b57cec5SDimitry Andric S += FieldName + ";\n"; 42190b57cec5SDimitry Andric } 42200b57cec5SDimitry Andric // Output all "by ref" declarations. 42210b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 42220b57cec5SDimitry Andric E = BlockByRefDecls.end(); I != E; ++I) { 42230b57cec5SDimitry Andric S += " "; 42240b57cec5SDimitry Andric std::string FieldName = (*I)->getNameAsString(); 42250b57cec5SDimitry Andric std::string ArgName = "_" + FieldName; 42260b57cec5SDimitry Andric { 42270b57cec5SDimitry Andric std::string TypeString; 42280b57cec5SDimitry Andric RewriteByRefString(TypeString, FieldName, (*I)); 42290b57cec5SDimitry Andric TypeString += " *"; 42300b57cec5SDimitry Andric FieldName = TypeString + FieldName; 42310b57cec5SDimitry Andric ArgName = TypeString + ArgName; 42320b57cec5SDimitry Andric Constructor += ", " + ArgName; 42330b57cec5SDimitry Andric } 42340b57cec5SDimitry Andric S += FieldName + "; // by ref\n"; 42350b57cec5SDimitry Andric } 42360b57cec5SDimitry Andric // Finish writing the constructor. 42370b57cec5SDimitry Andric Constructor += ", int flags=0)"; 42380b57cec5SDimitry Andric // Initialize all "by copy" arguments. 42390b57cec5SDimitry Andric bool firsTime = true; 42400b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 42410b57cec5SDimitry Andric E = BlockByCopyDecls.end(); I != E; ++I) { 42420b57cec5SDimitry Andric std::string Name = (*I)->getNameAsString(); 42430b57cec5SDimitry Andric if (firsTime) { 42440b57cec5SDimitry Andric Constructor += " : "; 42450b57cec5SDimitry Andric firsTime = false; 42460b57cec5SDimitry Andric } 42470b57cec5SDimitry Andric else 42480b57cec5SDimitry Andric Constructor += ", "; 42490b57cec5SDimitry Andric if (isTopLevelBlockPointerType((*I)->getType())) 42500b57cec5SDimitry Andric Constructor += Name + "((struct __block_impl *)_" + Name + ")"; 42510b57cec5SDimitry Andric else 42520b57cec5SDimitry Andric Constructor += Name + "(_" + Name + ")"; 42530b57cec5SDimitry Andric } 42540b57cec5SDimitry Andric // Initialize all "by ref" arguments. 42550b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 42560b57cec5SDimitry Andric E = BlockByRefDecls.end(); I != E; ++I) { 42570b57cec5SDimitry Andric std::string Name = (*I)->getNameAsString(); 42580b57cec5SDimitry Andric if (firsTime) { 42590b57cec5SDimitry Andric Constructor += " : "; 42600b57cec5SDimitry Andric firsTime = false; 42610b57cec5SDimitry Andric } 42620b57cec5SDimitry Andric else 42630b57cec5SDimitry Andric Constructor += ", "; 42640b57cec5SDimitry Andric Constructor += Name + "(_" + Name + "->__forwarding)"; 42650b57cec5SDimitry Andric } 42660b57cec5SDimitry Andric 42670b57cec5SDimitry Andric Constructor += " {\n"; 42680b57cec5SDimitry Andric if (GlobalVarDecl) 42690b57cec5SDimitry Andric Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 42700b57cec5SDimitry Andric else 42710b57cec5SDimitry Andric Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 42720b57cec5SDimitry Andric Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 42730b57cec5SDimitry Andric 42740b57cec5SDimitry Andric Constructor += " Desc = desc;\n"; 42750b57cec5SDimitry Andric } else { 42760b57cec5SDimitry Andric // Finish writing the constructor. 42770b57cec5SDimitry Andric Constructor += ", int flags=0) {\n"; 42780b57cec5SDimitry Andric if (GlobalVarDecl) 42790b57cec5SDimitry Andric Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 42800b57cec5SDimitry Andric else 42810b57cec5SDimitry Andric Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 42820b57cec5SDimitry Andric Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 42830b57cec5SDimitry Andric Constructor += " Desc = desc;\n"; 42840b57cec5SDimitry Andric } 42850b57cec5SDimitry Andric Constructor += " "; 42860b57cec5SDimitry Andric Constructor += "}\n"; 42870b57cec5SDimitry Andric S += Constructor; 42880b57cec5SDimitry Andric S += "};\n"; 42890b57cec5SDimitry Andric return S; 42900b57cec5SDimitry Andric } 42910b57cec5SDimitry Andric 4292*0fca6ea1SDimitry Andric std::string RewriteModernObjC::SynthesizeBlockDescriptor( 4293*0fca6ea1SDimitry Andric const std::string &DescTag, const std::string &ImplTag, int i, 4294*0fca6ea1SDimitry Andric StringRef FunName, unsigned hasCopy) { 42950b57cec5SDimitry Andric std::string S = "\nstatic struct " + DescTag; 42960b57cec5SDimitry Andric 42970b57cec5SDimitry Andric S += " {\n size_t reserved;\n"; 42980b57cec5SDimitry Andric S += " size_t Block_size;\n"; 42990b57cec5SDimitry Andric if (hasCopy) { 43000b57cec5SDimitry Andric S += " void (*copy)(struct "; 43010b57cec5SDimitry Andric S += ImplTag; S += "*, struct "; 43020b57cec5SDimitry Andric S += ImplTag; S += "*);\n"; 43030b57cec5SDimitry Andric 43040b57cec5SDimitry Andric S += " void (*dispose)(struct "; 43050b57cec5SDimitry Andric S += ImplTag; S += "*);\n"; 43060b57cec5SDimitry Andric } 43070b57cec5SDimitry Andric S += "} "; 43080b57cec5SDimitry Andric 43090b57cec5SDimitry Andric S += DescTag + "_DATA = { 0, sizeof(struct "; 43100b57cec5SDimitry Andric S += ImplTag + ")"; 43110b57cec5SDimitry Andric if (hasCopy) { 43120b57cec5SDimitry Andric S += ", __" + FunName.str() + "_block_copy_" + utostr(i); 43130b57cec5SDimitry Andric S += ", __" + FunName.str() + "_block_dispose_" + utostr(i); 43140b57cec5SDimitry Andric } 43150b57cec5SDimitry Andric S += "};\n"; 43160b57cec5SDimitry Andric return S; 43170b57cec5SDimitry Andric } 43180b57cec5SDimitry Andric 43190b57cec5SDimitry Andric void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, 43200b57cec5SDimitry Andric StringRef FunName) { 43210b57cec5SDimitry Andric bool RewriteSC = (GlobalVarDecl && 43220b57cec5SDimitry Andric !Blocks.empty() && 43230b57cec5SDimitry Andric GlobalVarDecl->getStorageClass() == SC_Static && 43240b57cec5SDimitry Andric GlobalVarDecl->getType().getCVRQualifiers()); 43250b57cec5SDimitry Andric if (RewriteSC) { 43260b57cec5SDimitry Andric std::string SC(" void __"); 43270b57cec5SDimitry Andric SC += GlobalVarDecl->getNameAsString(); 43280b57cec5SDimitry Andric SC += "() {}"; 43290b57cec5SDimitry Andric InsertText(FunLocStart, SC); 43300b57cec5SDimitry Andric } 43310b57cec5SDimitry Andric 43320b57cec5SDimitry Andric // Insert closures that were part of the function. 43330b57cec5SDimitry Andric for (unsigned i = 0, count=0; i < Blocks.size(); i++) { 43340b57cec5SDimitry Andric CollectBlockDeclRefInfo(Blocks[i]); 43350b57cec5SDimitry Andric // Need to copy-in the inner copied-in variables not actually used in this 43360b57cec5SDimitry Andric // block. 43370b57cec5SDimitry Andric for (int j = 0; j < InnerDeclRefsCount[i]; j++) { 43380b57cec5SDimitry Andric DeclRefExpr *Exp = InnerDeclRefs[count++]; 43390b57cec5SDimitry Andric ValueDecl *VD = Exp->getDecl(); 43400b57cec5SDimitry Andric BlockDeclRefs.push_back(Exp); 43410b57cec5SDimitry Andric if (!VD->hasAttr<BlocksAttr>()) { 43420b57cec5SDimitry Andric if (!BlockByCopyDeclsPtrSet.count(VD)) { 43430b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.insert(VD); 43440b57cec5SDimitry Andric BlockByCopyDecls.push_back(VD); 43450b57cec5SDimitry Andric } 43460b57cec5SDimitry Andric continue; 43470b57cec5SDimitry Andric } 43480b57cec5SDimitry Andric 43490b57cec5SDimitry Andric if (!BlockByRefDeclsPtrSet.count(VD)) { 43500b57cec5SDimitry Andric BlockByRefDeclsPtrSet.insert(VD); 43510b57cec5SDimitry Andric BlockByRefDecls.push_back(VD); 43520b57cec5SDimitry Andric } 43530b57cec5SDimitry Andric 43540b57cec5SDimitry Andric // imported objects in the inner blocks not used in the outer 43550b57cec5SDimitry Andric // blocks must be copied/disposed in the outer block as well. 43560b57cec5SDimitry Andric if (VD->getType()->isObjCObjectPointerType() || 43570b57cec5SDimitry Andric VD->getType()->isBlockPointerType()) 43580b57cec5SDimitry Andric ImportedBlockDecls.insert(VD); 43590b57cec5SDimitry Andric } 43600b57cec5SDimitry Andric 43610b57cec5SDimitry Andric std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i); 43620b57cec5SDimitry Andric std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i); 43630b57cec5SDimitry Andric 43640b57cec5SDimitry Andric std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); 43650b57cec5SDimitry Andric 43660b57cec5SDimitry Andric InsertText(FunLocStart, CI); 43670b57cec5SDimitry Andric 43680b57cec5SDimitry Andric std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); 43690b57cec5SDimitry Andric 43700b57cec5SDimitry Andric InsertText(FunLocStart, CF); 43710b57cec5SDimitry Andric 43720b57cec5SDimitry Andric if (ImportedBlockDecls.size()) { 43730b57cec5SDimitry Andric std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); 43740b57cec5SDimitry Andric InsertText(FunLocStart, HF); 43750b57cec5SDimitry Andric } 43760b57cec5SDimitry Andric std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, 43770b57cec5SDimitry Andric ImportedBlockDecls.size() > 0); 43780b57cec5SDimitry Andric InsertText(FunLocStart, BD); 43790b57cec5SDimitry Andric 43800b57cec5SDimitry Andric BlockDeclRefs.clear(); 43810b57cec5SDimitry Andric BlockByRefDecls.clear(); 43820b57cec5SDimitry Andric BlockByRefDeclsPtrSet.clear(); 43830b57cec5SDimitry Andric BlockByCopyDecls.clear(); 43840b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.clear(); 43850b57cec5SDimitry Andric ImportedBlockDecls.clear(); 43860b57cec5SDimitry Andric } 43870b57cec5SDimitry Andric if (RewriteSC) { 43880b57cec5SDimitry Andric // Must insert any 'const/volatile/static here. Since it has been 43890b57cec5SDimitry Andric // removed as result of rewriting of block literals. 43900b57cec5SDimitry Andric std::string SC; 43910b57cec5SDimitry Andric if (GlobalVarDecl->getStorageClass() == SC_Static) 43920b57cec5SDimitry Andric SC = "static "; 43930b57cec5SDimitry Andric if (GlobalVarDecl->getType().isConstQualified()) 43940b57cec5SDimitry Andric SC += "const "; 43950b57cec5SDimitry Andric if (GlobalVarDecl->getType().isVolatileQualified()) 43960b57cec5SDimitry Andric SC += "volatile "; 43970b57cec5SDimitry Andric if (GlobalVarDecl->getType().isRestrictQualified()) 43980b57cec5SDimitry Andric SC += "restrict "; 43990b57cec5SDimitry Andric InsertText(FunLocStart, SC); 44000b57cec5SDimitry Andric } 44010b57cec5SDimitry Andric if (GlobalConstructionExp) { 44020b57cec5SDimitry Andric // extra fancy dance for global literal expression. 44030b57cec5SDimitry Andric 44040b57cec5SDimitry Andric // Always the latest block expression on the block stack. 44050b57cec5SDimitry Andric std::string Tag = "__"; 44060b57cec5SDimitry Andric Tag += FunName; 44070b57cec5SDimitry Andric Tag += "_block_impl_"; 44080b57cec5SDimitry Andric Tag += utostr(Blocks.size()-1); 44090b57cec5SDimitry Andric std::string globalBuf = "static "; 44100b57cec5SDimitry Andric globalBuf += Tag; globalBuf += " "; 44110b57cec5SDimitry Andric std::string SStr; 44120b57cec5SDimitry Andric 44130b57cec5SDimitry Andric llvm::raw_string_ostream constructorExprBuf(SStr); 44140b57cec5SDimitry Andric GlobalConstructionExp->printPretty(constructorExprBuf, nullptr, 44150b57cec5SDimitry Andric PrintingPolicy(LangOpts)); 4416*0fca6ea1SDimitry Andric globalBuf += SStr; 44170b57cec5SDimitry Andric globalBuf += ";\n"; 44180b57cec5SDimitry Andric InsertText(FunLocStart, globalBuf); 44190b57cec5SDimitry Andric GlobalConstructionExp = nullptr; 44200b57cec5SDimitry Andric } 44210b57cec5SDimitry Andric 44220b57cec5SDimitry Andric Blocks.clear(); 44230b57cec5SDimitry Andric InnerDeclRefsCount.clear(); 44240b57cec5SDimitry Andric InnerDeclRefs.clear(); 44250b57cec5SDimitry Andric RewrittenBlockExprs.clear(); 44260b57cec5SDimitry Andric } 44270b57cec5SDimitry Andric 44280b57cec5SDimitry Andric void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { 44290b57cec5SDimitry Andric SourceLocation FunLocStart = 44300b57cec5SDimitry Andric (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD) 44310b57cec5SDimitry Andric : FD->getTypeSpecStartLoc(); 44320b57cec5SDimitry Andric StringRef FuncName = FD->getName(); 44330b57cec5SDimitry Andric 44340b57cec5SDimitry Andric SynthesizeBlockLiterals(FunLocStart, FuncName); 44350b57cec5SDimitry Andric } 44360b57cec5SDimitry Andric 44370b57cec5SDimitry Andric static void BuildUniqueMethodName(std::string &Name, 44380b57cec5SDimitry Andric ObjCMethodDecl *MD) { 44390b57cec5SDimitry Andric ObjCInterfaceDecl *IFace = MD->getClassInterface(); 44405ffd83dbSDimitry Andric Name = std::string(IFace->getName()); 44410b57cec5SDimitry Andric Name += "__" + MD->getSelector().getAsString(); 44420b57cec5SDimitry Andric // Convert colons to underscores. 44430b57cec5SDimitry Andric std::string::size_type loc = 0; 44440b57cec5SDimitry Andric while ((loc = Name.find(':', loc)) != std::string::npos) 44450b57cec5SDimitry Andric Name.replace(loc, 1, "_"); 44460b57cec5SDimitry Andric } 44470b57cec5SDimitry Andric 44480b57cec5SDimitry Andric void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { 44490b57cec5SDimitry Andric // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); 44500b57cec5SDimitry Andric // SourceLocation FunLocStart = MD->getBeginLoc(); 44510b57cec5SDimitry Andric SourceLocation FunLocStart = MD->getBeginLoc(); 44520b57cec5SDimitry Andric std::string FuncName; 44530b57cec5SDimitry Andric BuildUniqueMethodName(FuncName, MD); 44540b57cec5SDimitry Andric SynthesizeBlockLiterals(FunLocStart, FuncName); 44550b57cec5SDimitry Andric } 44560b57cec5SDimitry Andric 44570b57cec5SDimitry Andric void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) { 44580b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 44590b57cec5SDimitry Andric if (SubStmt) { 44600b57cec5SDimitry Andric if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) 44610b57cec5SDimitry Andric GetBlockDeclRefExprs(CBE->getBody()); 44620b57cec5SDimitry Andric else 44630b57cec5SDimitry Andric GetBlockDeclRefExprs(SubStmt); 44640b57cec5SDimitry Andric } 44650b57cec5SDimitry Andric // Handle specific things. 44660b57cec5SDimitry Andric if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) 44670b57cec5SDimitry Andric if (DRE->refersToEnclosingVariableOrCapture() || 44680b57cec5SDimitry Andric HasLocalVariableExternalStorage(DRE->getDecl())) 44690b57cec5SDimitry Andric // FIXME: Handle enums. 44700b57cec5SDimitry Andric BlockDeclRefs.push_back(DRE); 44710b57cec5SDimitry Andric } 44720b57cec5SDimitry Andric 44730b57cec5SDimitry Andric void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S, 44740b57cec5SDimitry Andric SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs, 44750b57cec5SDimitry Andric llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) { 44760b57cec5SDimitry Andric for (Stmt *SubStmt : S->children()) 44770b57cec5SDimitry Andric if (SubStmt) { 44780b57cec5SDimitry Andric if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) { 44790b57cec5SDimitry Andric InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl())); 44800b57cec5SDimitry Andric GetInnerBlockDeclRefExprs(CBE->getBody(), 44810b57cec5SDimitry Andric InnerBlockDeclRefs, 44820b57cec5SDimitry Andric InnerContexts); 44830b57cec5SDimitry Andric } 44840b57cec5SDimitry Andric else 44850b57cec5SDimitry Andric GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts); 44860b57cec5SDimitry Andric } 44870b57cec5SDimitry Andric // Handle specific things. 44880b57cec5SDimitry Andric if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 44890b57cec5SDimitry Andric if (DRE->refersToEnclosingVariableOrCapture() || 44900b57cec5SDimitry Andric HasLocalVariableExternalStorage(DRE->getDecl())) { 44910b57cec5SDimitry Andric if (!InnerContexts.count(DRE->getDecl()->getDeclContext())) 44920b57cec5SDimitry Andric InnerBlockDeclRefs.push_back(DRE); 44930b57cec5SDimitry Andric if (VarDecl *Var = cast<VarDecl>(DRE->getDecl())) 44940b57cec5SDimitry Andric if (Var->isFunctionOrMethodVarDecl()) 44950b57cec5SDimitry Andric ImportedLocalExternalDecls.insert(Var); 44960b57cec5SDimitry Andric } 44970b57cec5SDimitry Andric } 44980b57cec5SDimitry Andric } 44990b57cec5SDimitry Andric 45000b57cec5SDimitry Andric /// convertObjCTypeToCStyleType - This routine converts such objc types 45010b57cec5SDimitry Andric /// as qualified objects, and blocks to their closest c/c++ types that 45020b57cec5SDimitry Andric /// it can. It returns true if input type was modified. 45030b57cec5SDimitry Andric bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) { 45040b57cec5SDimitry Andric QualType oldT = T; 45050b57cec5SDimitry Andric convertBlockPointerToFunctionPointer(T); 45060b57cec5SDimitry Andric if (T->isFunctionPointerType()) { 45070b57cec5SDimitry Andric QualType PointeeTy; 45080b57cec5SDimitry Andric if (const PointerType* PT = T->getAs<PointerType>()) { 45090b57cec5SDimitry Andric PointeeTy = PT->getPointeeType(); 45100b57cec5SDimitry Andric if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) { 45110b57cec5SDimitry Andric T = convertFunctionTypeOfBlocks(FT); 45120b57cec5SDimitry Andric T = Context->getPointerType(T); 45130b57cec5SDimitry Andric } 45140b57cec5SDimitry Andric } 45150b57cec5SDimitry Andric } 45160b57cec5SDimitry Andric 45170b57cec5SDimitry Andric convertToUnqualifiedObjCType(T); 45180b57cec5SDimitry Andric return T != oldT; 45190b57cec5SDimitry Andric } 45200b57cec5SDimitry Andric 45210b57cec5SDimitry Andric /// convertFunctionTypeOfBlocks - This routine converts a function type 45220b57cec5SDimitry Andric /// whose result type may be a block pointer or whose argument type(s) 45230b57cec5SDimitry Andric /// might be block pointers to an equivalent function type replacing 45240b57cec5SDimitry Andric /// all block pointers to function pointers. 45250b57cec5SDimitry Andric QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { 45260b57cec5SDimitry Andric const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 45270b57cec5SDimitry Andric // FTP will be null for closures that don't take arguments. 45280b57cec5SDimitry Andric // Generate a funky cast. 45290b57cec5SDimitry Andric SmallVector<QualType, 8> ArgTypes; 45300b57cec5SDimitry Andric QualType Res = FT->getReturnType(); 45310b57cec5SDimitry Andric bool modified = convertObjCTypeToCStyleType(Res); 45320b57cec5SDimitry Andric 45330b57cec5SDimitry Andric if (FTP) { 45340b57cec5SDimitry Andric for (auto &I : FTP->param_types()) { 45350b57cec5SDimitry Andric QualType t = I; 45360b57cec5SDimitry Andric // Make sure we convert "t (^)(...)" to "t (*)(...)". 45370b57cec5SDimitry Andric if (convertObjCTypeToCStyleType(t)) 45380b57cec5SDimitry Andric modified = true; 45390b57cec5SDimitry Andric ArgTypes.push_back(t); 45400b57cec5SDimitry Andric } 45410b57cec5SDimitry Andric } 45420b57cec5SDimitry Andric QualType FuncType; 45430b57cec5SDimitry Andric if (modified) 45440b57cec5SDimitry Andric FuncType = getSimpleFunctionType(Res, ArgTypes); 45450b57cec5SDimitry Andric else FuncType = QualType(FT, 0); 45460b57cec5SDimitry Andric return FuncType; 45470b57cec5SDimitry Andric } 45480b57cec5SDimitry Andric 45490b57cec5SDimitry Andric Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 45500b57cec5SDimitry Andric // Navigate to relevant type information. 45510b57cec5SDimitry Andric const BlockPointerType *CPT = nullptr; 45520b57cec5SDimitry Andric 45530b57cec5SDimitry Andric if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { 45540b57cec5SDimitry Andric CPT = DRE->getType()->getAs<BlockPointerType>(); 45550b57cec5SDimitry Andric } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { 45560b57cec5SDimitry Andric CPT = MExpr->getType()->getAs<BlockPointerType>(); 45570b57cec5SDimitry Andric } 45580b57cec5SDimitry Andric else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) { 45590b57cec5SDimitry Andric return SynthesizeBlockCall(Exp, PRE->getSubExpr()); 45600b57cec5SDimitry Andric } 45610b57cec5SDimitry Andric else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 45620b57cec5SDimitry Andric CPT = IEXPR->getType()->getAs<BlockPointerType>(); 45630b57cec5SDimitry Andric else if (const ConditionalOperator *CEXPR = 45640b57cec5SDimitry Andric dyn_cast<ConditionalOperator>(BlockExp)) { 45650b57cec5SDimitry Andric Expr *LHSExp = CEXPR->getLHS(); 45660b57cec5SDimitry Andric Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp); 45670b57cec5SDimitry Andric Expr *RHSExp = CEXPR->getRHS(); 45680b57cec5SDimitry Andric Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); 45690b57cec5SDimitry Andric Expr *CONDExp = CEXPR->getCond(); 4570fe6060f1SDimitry Andric ConditionalOperator *CondExpr = new (Context) ConditionalOperator( 4571fe6060f1SDimitry Andric CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(), 4572fe6060f1SDimitry Andric cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary); 45730b57cec5SDimitry Andric return CondExpr; 45740b57cec5SDimitry Andric } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { 45750b57cec5SDimitry Andric CPT = IRE->getType()->getAs<BlockPointerType>(); 45760b57cec5SDimitry Andric } else if (const PseudoObjectExpr *POE 45770b57cec5SDimitry Andric = dyn_cast<PseudoObjectExpr>(BlockExp)) { 45780b57cec5SDimitry Andric CPT = POE->getType()->castAs<BlockPointerType>(); 45790b57cec5SDimitry Andric } else { 45800b57cec5SDimitry Andric assert(false && "RewriteBlockClass: Bad type"); 45810b57cec5SDimitry Andric } 45820b57cec5SDimitry Andric assert(CPT && "RewriteBlockClass: Bad type"); 45830b57cec5SDimitry Andric const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); 45840b57cec5SDimitry Andric assert(FT && "RewriteBlockClass: Bad type"); 45850b57cec5SDimitry Andric const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 45860b57cec5SDimitry Andric // FTP will be null for closures that don't take arguments. 45870b57cec5SDimitry Andric 45885f757f3fSDimitry Andric RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 45890b57cec5SDimitry Andric SourceLocation(), SourceLocation(), 45900b57cec5SDimitry Andric &Context->Idents.get("__block_impl")); 45910b57cec5SDimitry Andric QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); 45920b57cec5SDimitry Andric 45930b57cec5SDimitry Andric // Generate a funky cast. 45940b57cec5SDimitry Andric SmallVector<QualType, 8> ArgTypes; 45950b57cec5SDimitry Andric 45960b57cec5SDimitry Andric // Push the block argument type. 45970b57cec5SDimitry Andric ArgTypes.push_back(PtrBlock); 45980b57cec5SDimitry Andric if (FTP) { 45990b57cec5SDimitry Andric for (auto &I : FTP->param_types()) { 46000b57cec5SDimitry Andric QualType t = I; 46010b57cec5SDimitry Andric // Make sure we convert "t (^)(...)" to "t (*)(...)". 46020b57cec5SDimitry Andric if (!convertBlockPointerToFunctionPointer(t)) 46030b57cec5SDimitry Andric convertToUnqualifiedObjCType(t); 46040b57cec5SDimitry Andric ArgTypes.push_back(t); 46050b57cec5SDimitry Andric } 46060b57cec5SDimitry Andric } 46070b57cec5SDimitry Andric // Now do the pointer to function cast. 46080b57cec5SDimitry Andric QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes); 46090b57cec5SDimitry Andric 46100b57cec5SDimitry Andric PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); 46110b57cec5SDimitry Andric 46120b57cec5SDimitry Andric CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock, 46130b57cec5SDimitry Andric CK_BitCast, 46140b57cec5SDimitry Andric const_cast<Expr*>(BlockExp)); 46150b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 46160b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 46170b57cec5SDimitry Andric BlkCast); 46180b57cec5SDimitry Andric //PE->dump(); 46190b57cec5SDimitry Andric 46200b57cec5SDimitry Andric FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 46210b57cec5SDimitry Andric SourceLocation(), 46220b57cec5SDimitry Andric &Context->Idents.get("FuncPtr"), 46230b57cec5SDimitry Andric Context->VoidPtrTy, nullptr, 46240b57cec5SDimitry Andric /*BitWidth=*/nullptr, /*Mutable=*/true, 46250b57cec5SDimitry Andric ICIS_NoInit); 46260b57cec5SDimitry Andric MemberExpr *ME = MemberExpr::CreateImplicit( 46270b57cec5SDimitry Andric *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); 46280b57cec5SDimitry Andric 46290b57cec5SDimitry Andric CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, 46300b57cec5SDimitry Andric CK_BitCast, ME); 46310b57cec5SDimitry Andric PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); 46320b57cec5SDimitry Andric 46330b57cec5SDimitry Andric SmallVector<Expr*, 8> BlkExprs; 46340b57cec5SDimitry Andric // Add the implicit argument. 46350b57cec5SDimitry Andric BlkExprs.push_back(BlkCast); 46360b57cec5SDimitry Andric // Add the user arguments. 46370b57cec5SDimitry Andric for (CallExpr::arg_iterator I = Exp->arg_begin(), 46380b57cec5SDimitry Andric E = Exp->arg_end(); I != E; ++I) { 46390b57cec5SDimitry Andric BlkExprs.push_back(*I); 46400b57cec5SDimitry Andric } 4641e8d8bef9SDimitry Andric CallExpr *CE = 4642fe6060f1SDimitry Andric CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue, 4643e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 46440b57cec5SDimitry Andric return CE; 46450b57cec5SDimitry Andric } 46460b57cec5SDimitry Andric 46470b57cec5SDimitry Andric // We need to return the rewritten expression to handle cases where the 46480b57cec5SDimitry Andric // DeclRefExpr is embedded in another expression being rewritten. 46490b57cec5SDimitry Andric // For example: 46500b57cec5SDimitry Andric // 46510b57cec5SDimitry Andric // int main() { 46520b57cec5SDimitry Andric // __block Foo *f; 46530b57cec5SDimitry Andric // __block int i; 46540b57cec5SDimitry Andric // 46550b57cec5SDimitry Andric // void (^myblock)() = ^() { 46560b57cec5SDimitry Andric // [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten). 46570b57cec5SDimitry Andric // i = 77; 46580b57cec5SDimitry Andric // }; 46590b57cec5SDimitry Andric //} 46600b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { 46610b57cec5SDimitry Andric // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 46620b57cec5SDimitry Andric // for each DeclRefExp where BYREFVAR is name of the variable. 46630b57cec5SDimitry Andric ValueDecl *VD = DeclRefExp->getDecl(); 46640b57cec5SDimitry Andric bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() || 46650b57cec5SDimitry Andric HasLocalVariableExternalStorage(DeclRefExp->getDecl()); 46660b57cec5SDimitry Andric 46670b57cec5SDimitry Andric FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 46680b57cec5SDimitry Andric SourceLocation(), 46690b57cec5SDimitry Andric &Context->Idents.get("__forwarding"), 46700b57cec5SDimitry Andric Context->VoidPtrTy, nullptr, 46710b57cec5SDimitry Andric /*BitWidth=*/nullptr, /*Mutable=*/true, 46720b57cec5SDimitry Andric ICIS_NoInit); 46730b57cec5SDimitry Andric MemberExpr *ME = MemberExpr::CreateImplicit( 46740b57cec5SDimitry Andric *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary); 46750b57cec5SDimitry Andric 46760b57cec5SDimitry Andric StringRef Name = VD->getName(); 46770b57cec5SDimitry Andric FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(), 46780b57cec5SDimitry Andric &Context->Idents.get(Name), 46790b57cec5SDimitry Andric Context->VoidPtrTy, nullptr, 46800b57cec5SDimitry Andric /*BitWidth=*/nullptr, /*Mutable=*/true, 46810b57cec5SDimitry Andric ICIS_NoInit); 46820b57cec5SDimitry Andric ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(), 46830b57cec5SDimitry Andric VK_LValue, OK_Ordinary); 46840b57cec5SDimitry Andric 46850b57cec5SDimitry Andric // Need parens to enforce precedence. 46860b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 46870b57cec5SDimitry Andric DeclRefExp->getExprLoc(), 46880b57cec5SDimitry Andric ME); 46890b57cec5SDimitry Andric ReplaceStmt(DeclRefExp, PE); 46900b57cec5SDimitry Andric return PE; 46910b57cec5SDimitry Andric } 46920b57cec5SDimitry Andric 46930b57cec5SDimitry Andric // Rewrites the imported local variable V with external storage 46940b57cec5SDimitry Andric // (static, extern, etc.) as *V 46950b57cec5SDimitry Andric // 46960b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { 46970b57cec5SDimitry Andric ValueDecl *VD = DRE->getDecl(); 46980b57cec5SDimitry Andric if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 46990b57cec5SDimitry Andric if (!ImportedLocalExternalDecls.count(Var)) 47000b57cec5SDimitry Andric return DRE; 47015ffd83dbSDimitry Andric Expr *Exp = UnaryOperator::Create( 47025ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(), 47035ffd83dbSDimitry Andric VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride()); 47040b57cec5SDimitry Andric // Need parens to enforce precedence. 47050b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 47060b57cec5SDimitry Andric Exp); 47070b57cec5SDimitry Andric ReplaceStmt(DRE, PE); 47080b57cec5SDimitry Andric return PE; 47090b57cec5SDimitry Andric } 47100b57cec5SDimitry Andric 47110b57cec5SDimitry Andric void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) { 47120b57cec5SDimitry Andric SourceLocation LocStart = CE->getLParenLoc(); 47130b57cec5SDimitry Andric SourceLocation LocEnd = CE->getRParenLoc(); 47140b57cec5SDimitry Andric 47150b57cec5SDimitry Andric // Need to avoid trying to rewrite synthesized casts. 47160b57cec5SDimitry Andric if (LocStart.isInvalid()) 47170b57cec5SDimitry Andric return; 47180b57cec5SDimitry Andric // Need to avoid trying to rewrite casts contained in macros. 47190b57cec5SDimitry Andric if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) 47200b57cec5SDimitry Andric return; 47210b57cec5SDimitry Andric 47220b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(LocStart); 47230b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(LocEnd); 47240b57cec5SDimitry Andric QualType QT = CE->getType(); 47250b57cec5SDimitry Andric const Type* TypePtr = QT->getAs<Type>(); 47260b57cec5SDimitry Andric if (isa<TypeOfExprType>(TypePtr)) { 47270b57cec5SDimitry Andric const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 47280b57cec5SDimitry Andric QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 47290b57cec5SDimitry Andric std::string TypeAsString = "("; 47300b57cec5SDimitry Andric RewriteBlockPointerType(TypeAsString, QT); 47310b57cec5SDimitry Andric TypeAsString += ")"; 47320b57cec5SDimitry Andric ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); 47330b57cec5SDimitry Andric return; 47340b57cec5SDimitry Andric } 47350b57cec5SDimitry Andric // advance the location to startArgList. 47360b57cec5SDimitry Andric const char *argPtr = startBuf; 47370b57cec5SDimitry Andric 47380b57cec5SDimitry Andric while (*argPtr++ && (argPtr < endBuf)) { 47390b57cec5SDimitry Andric switch (*argPtr) { 47400b57cec5SDimitry Andric case '^': 47410b57cec5SDimitry Andric // Replace the '^' with '*'. 47420b57cec5SDimitry Andric LocStart = LocStart.getLocWithOffset(argPtr-startBuf); 47430b57cec5SDimitry Andric ReplaceText(LocStart, 1, "*"); 47440b57cec5SDimitry Andric break; 47450b57cec5SDimitry Andric } 47460b57cec5SDimitry Andric } 47470b57cec5SDimitry Andric } 47480b57cec5SDimitry Andric 47490b57cec5SDimitry Andric void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) { 47500b57cec5SDimitry Andric CastKind CastKind = IC->getCastKind(); 47510b57cec5SDimitry Andric if (CastKind != CK_BlockPointerToObjCPointerCast && 47520b57cec5SDimitry Andric CastKind != CK_AnyPointerToBlockPointerCast) 47530b57cec5SDimitry Andric return; 47540b57cec5SDimitry Andric 47550b57cec5SDimitry Andric QualType QT = IC->getType(); 47560b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(QT); 47570b57cec5SDimitry Andric std::string TypeString(QT.getAsString(Context->getPrintingPolicy())); 47580b57cec5SDimitry Andric std::string Str = "("; 47590b57cec5SDimitry Andric Str += TypeString; 47600b57cec5SDimitry Andric Str += ")"; 47610b57cec5SDimitry Andric InsertText(IC->getSubExpr()->getBeginLoc(), Str); 47620b57cec5SDimitry Andric } 47630b57cec5SDimitry Andric 47640b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { 47650b57cec5SDimitry Andric SourceLocation DeclLoc = FD->getLocation(); 47660b57cec5SDimitry Andric unsigned parenCount = 0; 47670b57cec5SDimitry Andric 47680b57cec5SDimitry Andric // We have 1 or more arguments that have closure pointers. 47690b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(DeclLoc); 47700b57cec5SDimitry Andric const char *startArgList = strchr(startBuf, '('); 47710b57cec5SDimitry Andric 47720b57cec5SDimitry Andric assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); 47730b57cec5SDimitry Andric 47740b57cec5SDimitry Andric parenCount++; 47750b57cec5SDimitry Andric // advance the location to startArgList. 47760b57cec5SDimitry Andric DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf); 47770b57cec5SDimitry Andric assert((DeclLoc.isValid()) && "Invalid DeclLoc"); 47780b57cec5SDimitry Andric 47790b57cec5SDimitry Andric const char *argPtr = startArgList; 47800b57cec5SDimitry Andric 47810b57cec5SDimitry Andric while (*argPtr++ && parenCount) { 47820b57cec5SDimitry Andric switch (*argPtr) { 47830b57cec5SDimitry Andric case '^': 47840b57cec5SDimitry Andric // Replace the '^' with '*'. 47850b57cec5SDimitry Andric DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList); 47860b57cec5SDimitry Andric ReplaceText(DeclLoc, 1, "*"); 47870b57cec5SDimitry Andric break; 47880b57cec5SDimitry Andric case '(': 47890b57cec5SDimitry Andric parenCount++; 47900b57cec5SDimitry Andric break; 47910b57cec5SDimitry Andric case ')': 47920b57cec5SDimitry Andric parenCount--; 47930b57cec5SDimitry Andric break; 47940b57cec5SDimitry Andric } 47950b57cec5SDimitry Andric } 47960b57cec5SDimitry Andric } 47970b57cec5SDimitry Andric 47980b57cec5SDimitry Andric bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { 47990b57cec5SDimitry Andric const FunctionProtoType *FTP; 48000b57cec5SDimitry Andric const PointerType *PT = QT->getAs<PointerType>(); 48010b57cec5SDimitry Andric if (PT) { 48020b57cec5SDimitry Andric FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 48030b57cec5SDimitry Andric } else { 48040b57cec5SDimitry Andric const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 48050b57cec5SDimitry Andric assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 48060b57cec5SDimitry Andric FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 48070b57cec5SDimitry Andric } 48080b57cec5SDimitry Andric if (FTP) { 48090b57cec5SDimitry Andric for (const auto &I : FTP->param_types()) 48100b57cec5SDimitry Andric if (isTopLevelBlockPointerType(I)) 48110b57cec5SDimitry Andric return true; 48120b57cec5SDimitry Andric } 48130b57cec5SDimitry Andric return false; 48140b57cec5SDimitry Andric } 48150b57cec5SDimitry Andric 48160b57cec5SDimitry Andric bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) { 48170b57cec5SDimitry Andric const FunctionProtoType *FTP; 48180b57cec5SDimitry Andric const PointerType *PT = QT->getAs<PointerType>(); 48190b57cec5SDimitry Andric if (PT) { 48200b57cec5SDimitry Andric FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 48210b57cec5SDimitry Andric } else { 48220b57cec5SDimitry Andric const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 48230b57cec5SDimitry Andric assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 48240b57cec5SDimitry Andric FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 48250b57cec5SDimitry Andric } 48260b57cec5SDimitry Andric if (FTP) { 48270b57cec5SDimitry Andric for (const auto &I : FTP->param_types()) { 48280b57cec5SDimitry Andric if (I->isObjCQualifiedIdType()) 48290b57cec5SDimitry Andric return true; 48300b57cec5SDimitry Andric if (I->isObjCObjectPointerType() && 48310b57cec5SDimitry Andric I->getPointeeType()->isObjCQualifiedInterfaceType()) 48320b57cec5SDimitry Andric return true; 48330b57cec5SDimitry Andric } 48340b57cec5SDimitry Andric 48350b57cec5SDimitry Andric } 48360b57cec5SDimitry Andric return false; 48370b57cec5SDimitry Andric } 48380b57cec5SDimitry Andric 48390b57cec5SDimitry Andric void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen, 48400b57cec5SDimitry Andric const char *&RParen) { 48410b57cec5SDimitry Andric const char *argPtr = strchr(Name, '('); 48420b57cec5SDimitry Andric assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); 48430b57cec5SDimitry Andric 48440b57cec5SDimitry Andric LParen = argPtr; // output the start. 48450b57cec5SDimitry Andric argPtr++; // skip past the left paren. 48460b57cec5SDimitry Andric unsigned parenCount = 1; 48470b57cec5SDimitry Andric 48480b57cec5SDimitry Andric while (*argPtr && parenCount) { 48490b57cec5SDimitry Andric switch (*argPtr) { 48500b57cec5SDimitry Andric case '(': parenCount++; break; 48510b57cec5SDimitry Andric case ')': parenCount--; break; 48520b57cec5SDimitry Andric default: break; 48530b57cec5SDimitry Andric } 48540b57cec5SDimitry Andric if (parenCount) argPtr++; 48550b57cec5SDimitry Andric } 48560b57cec5SDimitry Andric assert((*argPtr == ')') && "Rewriter fuzzy parser confused"); 48570b57cec5SDimitry Andric RParen = argPtr; // output the end 48580b57cec5SDimitry Andric } 48590b57cec5SDimitry Andric 48600b57cec5SDimitry Andric void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) { 48610b57cec5SDimitry Andric if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 48620b57cec5SDimitry Andric RewriteBlockPointerFunctionArgs(FD); 48630b57cec5SDimitry Andric return; 48640b57cec5SDimitry Andric } 48650b57cec5SDimitry Andric // Handle Variables and Typedefs. 48660b57cec5SDimitry Andric SourceLocation DeclLoc = ND->getLocation(); 48670b57cec5SDimitry Andric QualType DeclT; 48680b57cec5SDimitry Andric if (VarDecl *VD = dyn_cast<VarDecl>(ND)) 48690b57cec5SDimitry Andric DeclT = VD->getType(); 48700b57cec5SDimitry Andric else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND)) 48710b57cec5SDimitry Andric DeclT = TDD->getUnderlyingType(); 48720b57cec5SDimitry Andric else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) 48730b57cec5SDimitry Andric DeclT = FD->getType(); 48740b57cec5SDimitry Andric else 48750b57cec5SDimitry Andric llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled"); 48760b57cec5SDimitry Andric 48770b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(DeclLoc); 48780b57cec5SDimitry Andric const char *endBuf = startBuf; 48790b57cec5SDimitry Andric // scan backward (from the decl location) for the end of the previous decl. 48800b57cec5SDimitry Andric while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) 48810b57cec5SDimitry Andric startBuf--; 48820b57cec5SDimitry Andric SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf); 48830b57cec5SDimitry Andric std::string buf; 48840b57cec5SDimitry Andric unsigned OrigLength=0; 48850b57cec5SDimitry Andric // *startBuf != '^' if we are dealing with a pointer to function that 48860b57cec5SDimitry Andric // may take block argument types (which will be handled below). 48870b57cec5SDimitry Andric if (*startBuf == '^') { 48880b57cec5SDimitry Andric // Replace the '^' with '*', computing a negative offset. 48890b57cec5SDimitry Andric buf = '*'; 48900b57cec5SDimitry Andric startBuf++; 48910b57cec5SDimitry Andric OrigLength++; 48920b57cec5SDimitry Andric } 48930b57cec5SDimitry Andric while (*startBuf != ')') { 48940b57cec5SDimitry Andric buf += *startBuf; 48950b57cec5SDimitry Andric startBuf++; 48960b57cec5SDimitry Andric OrigLength++; 48970b57cec5SDimitry Andric } 48980b57cec5SDimitry Andric buf += ')'; 48990b57cec5SDimitry Andric OrigLength++; 49000b57cec5SDimitry Andric 49010b57cec5SDimitry Andric if (PointerTypeTakesAnyBlockArguments(DeclT) || 49020b57cec5SDimitry Andric PointerTypeTakesAnyObjCQualifiedType(DeclT)) { 49030b57cec5SDimitry Andric // Replace the '^' with '*' for arguments. 49040b57cec5SDimitry Andric // Replace id<P> with id/*<>*/ 49050b57cec5SDimitry Andric DeclLoc = ND->getLocation(); 49060b57cec5SDimitry Andric startBuf = SM->getCharacterData(DeclLoc); 49070b57cec5SDimitry Andric const char *argListBegin, *argListEnd; 49080b57cec5SDimitry Andric GetExtentOfArgList(startBuf, argListBegin, argListEnd); 49090b57cec5SDimitry Andric while (argListBegin < argListEnd) { 49100b57cec5SDimitry Andric if (*argListBegin == '^') 49110b57cec5SDimitry Andric buf += '*'; 49120b57cec5SDimitry Andric else if (*argListBegin == '<') { 49130b57cec5SDimitry Andric buf += "/*"; 49140b57cec5SDimitry Andric buf += *argListBegin++; 49150b57cec5SDimitry Andric OrigLength++; 49160b57cec5SDimitry Andric while (*argListBegin != '>') { 49170b57cec5SDimitry Andric buf += *argListBegin++; 49180b57cec5SDimitry Andric OrigLength++; 49190b57cec5SDimitry Andric } 49200b57cec5SDimitry Andric buf += *argListBegin; 49210b57cec5SDimitry Andric buf += "*/"; 49220b57cec5SDimitry Andric } 49230b57cec5SDimitry Andric else 49240b57cec5SDimitry Andric buf += *argListBegin; 49250b57cec5SDimitry Andric argListBegin++; 49260b57cec5SDimitry Andric OrigLength++; 49270b57cec5SDimitry Andric } 49280b57cec5SDimitry Andric buf += ')'; 49290b57cec5SDimitry Andric OrigLength++; 49300b57cec5SDimitry Andric } 49310b57cec5SDimitry Andric ReplaceText(Start, OrigLength, buf); 49320b57cec5SDimitry Andric } 49330b57cec5SDimitry Andric 49340b57cec5SDimitry Andric /// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: 49350b57cec5SDimitry Andric /// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, 49360b57cec5SDimitry Andric /// struct Block_byref_id_object *src) { 49370b57cec5SDimitry Andric /// _Block_object_assign (&_dest->object, _src->object, 49380b57cec5SDimitry Andric /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 49390b57cec5SDimitry Andric /// [|BLOCK_FIELD_IS_WEAK]) // object 49400b57cec5SDimitry Andric /// _Block_object_assign(&_dest->object, _src->object, 49410b57cec5SDimitry Andric /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 49420b57cec5SDimitry Andric /// [|BLOCK_FIELD_IS_WEAK]) // block 49430b57cec5SDimitry Andric /// } 49440b57cec5SDimitry Andric /// And: 49450b57cec5SDimitry Andric /// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { 49460b57cec5SDimitry Andric /// _Block_object_dispose(_src->object, 49470b57cec5SDimitry Andric /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 49480b57cec5SDimitry Andric /// [|BLOCK_FIELD_IS_WEAK]) // object 49490b57cec5SDimitry Andric /// _Block_object_dispose(_src->object, 49500b57cec5SDimitry Andric /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 49510b57cec5SDimitry Andric /// [|BLOCK_FIELD_IS_WEAK]) // block 49520b57cec5SDimitry Andric /// } 49530b57cec5SDimitry Andric 49540b57cec5SDimitry Andric std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, 49550b57cec5SDimitry Andric int flag) { 49560b57cec5SDimitry Andric std::string S; 49570b57cec5SDimitry Andric if (CopyDestroyCache.count(flag)) 49580b57cec5SDimitry Andric return S; 49590b57cec5SDimitry Andric CopyDestroyCache.insert(flag); 49600b57cec5SDimitry Andric S = "static void __Block_byref_id_object_copy_"; 49610b57cec5SDimitry Andric S += utostr(flag); 49620b57cec5SDimitry Andric S += "(void *dst, void *src) {\n"; 49630b57cec5SDimitry Andric 49640b57cec5SDimitry Andric // offset into the object pointer is computed as: 49650b57cec5SDimitry Andric // void * + void* + int + int + void* + void * 49660b57cec5SDimitry Andric unsigned IntSize = 49670b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 49680b57cec5SDimitry Andric unsigned VoidPtrSize = 49690b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); 49700b57cec5SDimitry Andric 49710b57cec5SDimitry Andric unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth(); 49720b57cec5SDimitry Andric S += " _Block_object_assign((char*)dst + "; 49730b57cec5SDimitry Andric S += utostr(offset); 49740b57cec5SDimitry Andric S += ", *(void * *) ((char*)src + "; 49750b57cec5SDimitry Andric S += utostr(offset); 49760b57cec5SDimitry Andric S += "), "; 49770b57cec5SDimitry Andric S += utostr(flag); 49780b57cec5SDimitry Andric S += ");\n}\n"; 49790b57cec5SDimitry Andric 49800b57cec5SDimitry Andric S += "static void __Block_byref_id_object_dispose_"; 49810b57cec5SDimitry Andric S += utostr(flag); 49820b57cec5SDimitry Andric S += "(void *src) {\n"; 49830b57cec5SDimitry Andric S += " _Block_object_dispose(*(void * *) ((char*)src + "; 49840b57cec5SDimitry Andric S += utostr(offset); 49850b57cec5SDimitry Andric S += "), "; 49860b57cec5SDimitry Andric S += utostr(flag); 49870b57cec5SDimitry Andric S += ");\n}\n"; 49880b57cec5SDimitry Andric return S; 49890b57cec5SDimitry Andric } 49900b57cec5SDimitry Andric 49910b57cec5SDimitry Andric /// RewriteByRefVar - For each __block typex ND variable this routine transforms 49920b57cec5SDimitry Andric /// the declaration into: 49930b57cec5SDimitry Andric /// struct __Block_byref_ND { 49940b57cec5SDimitry Andric /// void *__isa; // NULL for everything except __weak pointers 49950b57cec5SDimitry Andric /// struct __Block_byref_ND *__forwarding; 49960b57cec5SDimitry Andric /// int32_t __flags; 49970b57cec5SDimitry Andric /// int32_t __size; 49980b57cec5SDimitry Andric /// void *__Block_byref_id_object_copy; // If variable is __block ObjC object 49990b57cec5SDimitry Andric /// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object 50000b57cec5SDimitry Andric /// typex ND; 50010b57cec5SDimitry Andric /// }; 50020b57cec5SDimitry Andric /// 50030b57cec5SDimitry Andric /// It then replaces declaration of ND variable with: 50040b57cec5SDimitry Andric /// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 50050b57cec5SDimitry Andric /// __size=sizeof(struct __Block_byref_ND), 50060b57cec5SDimitry Andric /// ND=initializer-if-any}; 50070b57cec5SDimitry Andric /// 50080b57cec5SDimitry Andric /// 50090b57cec5SDimitry Andric void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl, 50100b57cec5SDimitry Andric bool lastDecl) { 50110b57cec5SDimitry Andric int flag = 0; 50120b57cec5SDimitry Andric int isa = 0; 50130b57cec5SDimitry Andric SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 50140b57cec5SDimitry Andric if (DeclLoc.isInvalid()) 50150b57cec5SDimitry Andric // If type location is missing, it is because of missing type (a warning). 50160b57cec5SDimitry Andric // Use variable's location which is good for this case. 50170b57cec5SDimitry Andric DeclLoc = ND->getLocation(); 50180b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(DeclLoc); 50190b57cec5SDimitry Andric SourceLocation X = ND->getEndLoc(); 50200b57cec5SDimitry Andric X = SM->getExpansionLoc(X); 50210b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(X); 50220b57cec5SDimitry Andric std::string Name(ND->getNameAsString()); 50230b57cec5SDimitry Andric std::string ByrefType; 50240b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND, true); 50250b57cec5SDimitry Andric ByrefType += " {\n"; 50260b57cec5SDimitry Andric ByrefType += " void *__isa;\n"; 50270b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND); 50280b57cec5SDimitry Andric ByrefType += " *__forwarding;\n"; 50290b57cec5SDimitry Andric ByrefType += " int __flags;\n"; 50300b57cec5SDimitry Andric ByrefType += " int __size;\n"; 50310b57cec5SDimitry Andric // Add void *__Block_byref_id_object_copy; 50320b57cec5SDimitry Andric // void *__Block_byref_id_object_dispose; if needed. 50330b57cec5SDimitry Andric QualType Ty = ND->getType(); 50340b57cec5SDimitry Andric bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND); 50350b57cec5SDimitry Andric if (HasCopyAndDispose) { 50360b57cec5SDimitry Andric ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; 50370b57cec5SDimitry Andric ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; 50380b57cec5SDimitry Andric } 50390b57cec5SDimitry Andric 50400b57cec5SDimitry Andric QualType T = Ty; 50410b57cec5SDimitry Andric (void)convertBlockPointerToFunctionPointer(T); 50420b57cec5SDimitry Andric T.getAsStringInternal(Name, Context->getPrintingPolicy()); 50430b57cec5SDimitry Andric 50440b57cec5SDimitry Andric ByrefType += " " + Name + ";\n"; 50450b57cec5SDimitry Andric ByrefType += "};\n"; 50460b57cec5SDimitry Andric // Insert this type in global scope. It is needed by helper function. 50470b57cec5SDimitry Andric SourceLocation FunLocStart; 50480b57cec5SDimitry Andric if (CurFunctionDef) 50490b57cec5SDimitry Andric FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef); 50500b57cec5SDimitry Andric else { 50510b57cec5SDimitry Andric assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); 50520b57cec5SDimitry Andric FunLocStart = CurMethodDef->getBeginLoc(); 50530b57cec5SDimitry Andric } 50540b57cec5SDimitry Andric InsertText(FunLocStart, ByrefType); 50550b57cec5SDimitry Andric 50560b57cec5SDimitry Andric if (Ty.isObjCGCWeak()) { 50570b57cec5SDimitry Andric flag |= BLOCK_FIELD_IS_WEAK; 50580b57cec5SDimitry Andric isa = 1; 50590b57cec5SDimitry Andric } 50600b57cec5SDimitry Andric if (HasCopyAndDispose) { 50610b57cec5SDimitry Andric flag = BLOCK_BYREF_CALLER; 50620b57cec5SDimitry Andric QualType Ty = ND->getType(); 50630b57cec5SDimitry Andric // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. 50640b57cec5SDimitry Andric if (Ty->isBlockPointerType()) 50650b57cec5SDimitry Andric flag |= BLOCK_FIELD_IS_BLOCK; 50660b57cec5SDimitry Andric else 50670b57cec5SDimitry Andric flag |= BLOCK_FIELD_IS_OBJECT; 50680b57cec5SDimitry Andric std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); 50690b57cec5SDimitry Andric if (!HF.empty()) 50700b57cec5SDimitry Andric Preamble += HF; 50710b57cec5SDimitry Andric } 50720b57cec5SDimitry Andric 50730b57cec5SDimitry Andric // struct __Block_byref_ND ND = 50740b57cec5SDimitry Andric // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 50750b57cec5SDimitry Andric // initializer-if-any}; 50760b57cec5SDimitry Andric bool hasInit = (ND->getInit() != nullptr); 50770b57cec5SDimitry Andric // FIXME. rewriter does not support __block c++ objects which 50780b57cec5SDimitry Andric // require construction. 50790b57cec5SDimitry Andric if (hasInit) 50800b57cec5SDimitry Andric if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) { 50810b57cec5SDimitry Andric CXXConstructorDecl *CXXDecl = CExp->getConstructor(); 50820b57cec5SDimitry Andric if (CXXDecl && CXXDecl->isDefaultConstructor()) 50830b57cec5SDimitry Andric hasInit = false; 50840b57cec5SDimitry Andric } 50850b57cec5SDimitry Andric 50860b57cec5SDimitry Andric unsigned flags = 0; 50870b57cec5SDimitry Andric if (HasCopyAndDispose) 50880b57cec5SDimitry Andric flags |= BLOCK_HAS_COPY_DISPOSE; 50890b57cec5SDimitry Andric Name = ND->getNameAsString(); 50900b57cec5SDimitry Andric ByrefType.clear(); 50910b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND); 50920b57cec5SDimitry Andric std::string ForwardingCastType("("); 50930b57cec5SDimitry Andric ForwardingCastType += ByrefType + " *)"; 50940b57cec5SDimitry Andric ByrefType += " " + Name + " = {(void*)"; 50950b57cec5SDimitry Andric ByrefType += utostr(isa); 50960b57cec5SDimitry Andric ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 50970b57cec5SDimitry Andric ByrefType += utostr(flags); 50980b57cec5SDimitry Andric ByrefType += ", "; 50990b57cec5SDimitry Andric ByrefType += "sizeof("; 51000b57cec5SDimitry Andric RewriteByRefString(ByrefType, Name, ND); 51010b57cec5SDimitry Andric ByrefType += ")"; 51020b57cec5SDimitry Andric if (HasCopyAndDispose) { 51030b57cec5SDimitry Andric ByrefType += ", __Block_byref_id_object_copy_"; 51040b57cec5SDimitry Andric ByrefType += utostr(flag); 51050b57cec5SDimitry Andric ByrefType += ", __Block_byref_id_object_dispose_"; 51060b57cec5SDimitry Andric ByrefType += utostr(flag); 51070b57cec5SDimitry Andric } 51080b57cec5SDimitry Andric 51090b57cec5SDimitry Andric if (!firstDecl) { 51100b57cec5SDimitry Andric // In multiple __block declarations, and for all but 1st declaration, 51110b57cec5SDimitry Andric // find location of the separating comma. This would be start location 51120b57cec5SDimitry Andric // where new text is to be inserted. 51130b57cec5SDimitry Andric DeclLoc = ND->getLocation(); 51140b57cec5SDimitry Andric const char *startDeclBuf = SM->getCharacterData(DeclLoc); 51150b57cec5SDimitry Andric const char *commaBuf = startDeclBuf; 51160b57cec5SDimitry Andric while (*commaBuf != ',') 51170b57cec5SDimitry Andric commaBuf--; 51180b57cec5SDimitry Andric assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','"); 51190b57cec5SDimitry Andric DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf); 51200b57cec5SDimitry Andric startBuf = commaBuf; 51210b57cec5SDimitry Andric } 51220b57cec5SDimitry Andric 51230b57cec5SDimitry Andric if (!hasInit) { 51240b57cec5SDimitry Andric ByrefType += "};\n"; 51250b57cec5SDimitry Andric unsigned nameSize = Name.size(); 51260b57cec5SDimitry Andric // for block or function pointer declaration. Name is already 51270b57cec5SDimitry Andric // part of the declaration. 51280b57cec5SDimitry Andric if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) 51290b57cec5SDimitry Andric nameSize = 1; 51300b57cec5SDimitry Andric ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType); 51310b57cec5SDimitry Andric } 51320b57cec5SDimitry Andric else { 51330b57cec5SDimitry Andric ByrefType += ", "; 51340b57cec5SDimitry Andric SourceLocation startLoc; 51350b57cec5SDimitry Andric Expr *E = ND->getInit(); 51360b57cec5SDimitry Andric if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 51370b57cec5SDimitry Andric startLoc = ECE->getLParenLoc(); 51380b57cec5SDimitry Andric else 51390b57cec5SDimitry Andric startLoc = E->getBeginLoc(); 51400b57cec5SDimitry Andric startLoc = SM->getExpansionLoc(startLoc); 51410b57cec5SDimitry Andric endBuf = SM->getCharacterData(startLoc); 51420b57cec5SDimitry Andric ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); 51430b57cec5SDimitry Andric 51440b57cec5SDimitry Andric const char separator = lastDecl ? ';' : ','; 51450b57cec5SDimitry Andric const char *startInitializerBuf = SM->getCharacterData(startLoc); 51460b57cec5SDimitry Andric const char *separatorBuf = strchr(startInitializerBuf, separator); 51470b57cec5SDimitry Andric assert((*separatorBuf == separator) && 51480b57cec5SDimitry Andric "RewriteByRefVar: can't find ';' or ','"); 51490b57cec5SDimitry Andric SourceLocation separatorLoc = 51500b57cec5SDimitry Andric startLoc.getLocWithOffset(separatorBuf-startInitializerBuf); 51510b57cec5SDimitry Andric 51520b57cec5SDimitry Andric InsertText(separatorLoc, lastDecl ? "}" : "};\n"); 51530b57cec5SDimitry Andric } 51540b57cec5SDimitry Andric } 51550b57cec5SDimitry Andric 51560b57cec5SDimitry Andric void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { 51570b57cec5SDimitry Andric // Add initializers for any closure decl refs. 51580b57cec5SDimitry Andric GetBlockDeclRefExprs(Exp->getBody()); 51590b57cec5SDimitry Andric if (BlockDeclRefs.size()) { 51600b57cec5SDimitry Andric // Unique all "by copy" declarations. 51610b57cec5SDimitry Andric for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 51620b57cec5SDimitry Andric if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 51630b57cec5SDimitry Andric if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 51640b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 51650b57cec5SDimitry Andric BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); 51660b57cec5SDimitry Andric } 51670b57cec5SDimitry Andric } 51680b57cec5SDimitry Andric // Unique all "by ref" declarations. 51690b57cec5SDimitry Andric for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 51700b57cec5SDimitry Andric if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 51710b57cec5SDimitry Andric if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 51720b57cec5SDimitry Andric BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 51730b57cec5SDimitry Andric BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); 51740b57cec5SDimitry Andric } 51750b57cec5SDimitry Andric } 51760b57cec5SDimitry Andric // Find any imported blocks...they will need special attention. 51770b57cec5SDimitry Andric for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 51780b57cec5SDimitry Andric if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 51790b57cec5SDimitry Andric BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 51800b57cec5SDimitry Andric BlockDeclRefs[i]->getType()->isBlockPointerType()) 51810b57cec5SDimitry Andric ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); 51820b57cec5SDimitry Andric } 51830b57cec5SDimitry Andric } 51840b57cec5SDimitry Andric 51850b57cec5SDimitry Andric FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) { 51860b57cec5SDimitry Andric IdentifierInfo *ID = &Context->Idents.get(name); 51870b57cec5SDimitry Andric QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); 51880b57cec5SDimitry Andric return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), 51890b57cec5SDimitry Andric SourceLocation(), ID, FType, nullptr, SC_Extern, 51900b57cec5SDimitry Andric false, false); 51910b57cec5SDimitry Andric } 51920b57cec5SDimitry Andric 51930b57cec5SDimitry Andric Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, 51940b57cec5SDimitry Andric const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) { 51950b57cec5SDimitry Andric const BlockDecl *block = Exp->getBlockDecl(); 51960b57cec5SDimitry Andric 51970b57cec5SDimitry Andric Blocks.push_back(Exp); 51980b57cec5SDimitry Andric 51990b57cec5SDimitry Andric CollectBlockDeclRefInfo(Exp); 52000b57cec5SDimitry Andric 52010b57cec5SDimitry Andric // Add inner imported variables now used in current block. 52020b57cec5SDimitry Andric int countOfInnerDecls = 0; 52030b57cec5SDimitry Andric if (!InnerBlockDeclRefs.empty()) { 52040b57cec5SDimitry Andric for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { 52050b57cec5SDimitry Andric DeclRefExpr *Exp = InnerBlockDeclRefs[i]; 52060b57cec5SDimitry Andric ValueDecl *VD = Exp->getDecl(); 52070b57cec5SDimitry Andric if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { 52080b57cec5SDimitry Andric // We need to save the copied-in variables in nested 52090b57cec5SDimitry Andric // blocks because it is needed at the end for some of the API generations. 52100b57cec5SDimitry Andric // See SynthesizeBlockLiterals routine. 52110b57cec5SDimitry Andric InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 52120b57cec5SDimitry Andric BlockDeclRefs.push_back(Exp); 52130b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.insert(VD); 52140b57cec5SDimitry Andric BlockByCopyDecls.push_back(VD); 52150b57cec5SDimitry Andric } 52160b57cec5SDimitry Andric if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { 52170b57cec5SDimitry Andric InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 52180b57cec5SDimitry Andric BlockDeclRefs.push_back(Exp); 52190b57cec5SDimitry Andric BlockByRefDeclsPtrSet.insert(VD); 52200b57cec5SDimitry Andric BlockByRefDecls.push_back(VD); 52210b57cec5SDimitry Andric } 52220b57cec5SDimitry Andric } 52230b57cec5SDimitry Andric // Find any imported blocks...they will need special attention. 52240b57cec5SDimitry Andric for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) 52250b57cec5SDimitry Andric if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 52260b57cec5SDimitry Andric InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 52270b57cec5SDimitry Andric InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) 52280b57cec5SDimitry Andric ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); 52290b57cec5SDimitry Andric } 52300b57cec5SDimitry Andric InnerDeclRefsCount.push_back(countOfInnerDecls); 52310b57cec5SDimitry Andric 52320b57cec5SDimitry Andric std::string FuncName; 52330b57cec5SDimitry Andric 52340b57cec5SDimitry Andric if (CurFunctionDef) 52350b57cec5SDimitry Andric FuncName = CurFunctionDef->getNameAsString(); 52360b57cec5SDimitry Andric else if (CurMethodDef) 52370b57cec5SDimitry Andric BuildUniqueMethodName(FuncName, CurMethodDef); 52380b57cec5SDimitry Andric else if (GlobalVarDecl) 52390b57cec5SDimitry Andric FuncName = std::string(GlobalVarDecl->getNameAsString()); 52400b57cec5SDimitry Andric 52410b57cec5SDimitry Andric bool GlobalBlockExpr = 52420b57cec5SDimitry Andric block->getDeclContext()->getRedeclContext()->isFileContext(); 52430b57cec5SDimitry Andric 52440b57cec5SDimitry Andric if (GlobalBlockExpr && !GlobalVarDecl) { 52450b57cec5SDimitry Andric Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag); 52460b57cec5SDimitry Andric GlobalBlockExpr = false; 52470b57cec5SDimitry Andric } 52480b57cec5SDimitry Andric 52490b57cec5SDimitry Andric std::string BlockNumber = utostr(Blocks.size()-1); 52500b57cec5SDimitry Andric 52510b57cec5SDimitry Andric std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; 52520b57cec5SDimitry Andric 52530b57cec5SDimitry Andric // Get a pointer to the function type so we can cast appropriately. 52540b57cec5SDimitry Andric QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType()); 52550b57cec5SDimitry Andric QualType FType = Context->getPointerType(BFT); 52560b57cec5SDimitry Andric 52570b57cec5SDimitry Andric FunctionDecl *FD; 52580b57cec5SDimitry Andric Expr *NewRep; 52590b57cec5SDimitry Andric 52600b57cec5SDimitry Andric // Simulate a constructor call... 52610b57cec5SDimitry Andric std::string Tag; 52620b57cec5SDimitry Andric 52630b57cec5SDimitry Andric if (GlobalBlockExpr) 52640b57cec5SDimitry Andric Tag = "__global_"; 52650b57cec5SDimitry Andric else 52660b57cec5SDimitry Andric Tag = "__"; 52670b57cec5SDimitry Andric Tag += FuncName + "_block_impl_" + BlockNumber; 52680b57cec5SDimitry Andric 52690b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl(Tag); 52700b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 5271fe6060f1SDimitry Andric DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation()); 52720b57cec5SDimitry Andric 52730b57cec5SDimitry Andric SmallVector<Expr*, 4> InitExprs; 52740b57cec5SDimitry Andric 52750b57cec5SDimitry Andric // Initialize the block function. 52760b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl(Func); 52770b57cec5SDimitry Andric DeclRefExpr *Arg = new (Context) DeclRefExpr( 52780b57cec5SDimitry Andric *Context, FD, false, FD->getType(), VK_LValue, SourceLocation()); 52790b57cec5SDimitry Andric CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 52800b57cec5SDimitry Andric CK_BitCast, Arg); 52810b57cec5SDimitry Andric InitExprs.push_back(castExpr); 52820b57cec5SDimitry Andric 52830b57cec5SDimitry Andric // Initialize the block descriptor. 52840b57cec5SDimitry Andric std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; 52850b57cec5SDimitry Andric 52860b57cec5SDimitry Andric VarDecl *NewVD = VarDecl::Create( 52870b57cec5SDimitry Andric *Context, TUDecl, SourceLocation(), SourceLocation(), 52880b57cec5SDimitry Andric &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static); 52895ffd83dbSDimitry Andric UnaryOperator *DescRefExpr = UnaryOperator::Create( 52905ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), 52910b57cec5SDimitry Andric new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy, 52920b57cec5SDimitry Andric VK_LValue, SourceLocation()), 5293fe6060f1SDimitry Andric UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue, 52945ffd83dbSDimitry Andric OK_Ordinary, SourceLocation(), false, FPOptionsOverride()); 52950b57cec5SDimitry Andric InitExprs.push_back(DescRefExpr); 52960b57cec5SDimitry Andric 52970b57cec5SDimitry Andric // Add initializers for any closure decl refs. 52980b57cec5SDimitry Andric if (BlockDeclRefs.size()) { 52990b57cec5SDimitry Andric Expr *Exp; 53000b57cec5SDimitry Andric // Output all "by copy" declarations. 53010b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 53020b57cec5SDimitry Andric E = BlockByCopyDecls.end(); I != E; ++I) { 53030b57cec5SDimitry Andric if (isObjCType((*I)->getType())) { 53040b57cec5SDimitry Andric // FIXME: Conform to ABI ([[obj retain] autorelease]). 53050b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl((*I)->getName()); 53060b57cec5SDimitry Andric Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(), 53070b57cec5SDimitry Andric VK_LValue, SourceLocation()); 53080b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(*I)) { 53090b57cec5SDimitry Andric QualType QT = (*I)->getType(); 53100b57cec5SDimitry Andric QT = Context->getPointerType(QT); 5311fe6060f1SDimitry Andric Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp, 5312fe6060f1SDimitry Andric UO_AddrOf, QT, VK_PRValue, OK_Ordinary, 5313fe6060f1SDimitry Andric SourceLocation(), false, 5314fe6060f1SDimitry Andric FPOptionsOverride()); 53150b57cec5SDimitry Andric } 53160b57cec5SDimitry Andric } else if (isTopLevelBlockPointerType((*I)->getType())) { 53170b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl((*I)->getName()); 53180b57cec5SDimitry Andric Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(), 53190b57cec5SDimitry Andric VK_LValue, SourceLocation()); 53200b57cec5SDimitry Andric Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 53210b57cec5SDimitry Andric CK_BitCast, Arg); 53220b57cec5SDimitry Andric } else { 53230b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl((*I)->getName()); 53240b57cec5SDimitry Andric Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(), 53250b57cec5SDimitry Andric VK_LValue, SourceLocation()); 53260b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(*I)) { 53270b57cec5SDimitry Andric QualType QT = (*I)->getType(); 53280b57cec5SDimitry Andric QT = Context->getPointerType(QT); 5329fe6060f1SDimitry Andric Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp, 5330fe6060f1SDimitry Andric UO_AddrOf, QT, VK_PRValue, OK_Ordinary, 5331fe6060f1SDimitry Andric SourceLocation(), false, 5332fe6060f1SDimitry Andric FPOptionsOverride()); 53330b57cec5SDimitry Andric } 53340b57cec5SDimitry Andric 53350b57cec5SDimitry Andric } 53360b57cec5SDimitry Andric InitExprs.push_back(Exp); 53370b57cec5SDimitry Andric } 53380b57cec5SDimitry Andric // Output all "by ref" declarations. 53390b57cec5SDimitry Andric for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 53400b57cec5SDimitry Andric E = BlockByRefDecls.end(); I != E; ++I) { 53410b57cec5SDimitry Andric ValueDecl *ND = (*I); 53420b57cec5SDimitry Andric std::string Name(ND->getNameAsString()); 53430b57cec5SDimitry Andric std::string RecName; 53440b57cec5SDimitry Andric RewriteByRefString(RecName, Name, ND, true); 53450b57cec5SDimitry Andric IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 53460b57cec5SDimitry Andric + sizeof("struct")); 53475f757f3fSDimitry Andric RecordDecl *RD = 53485f757f3fSDimitry Andric RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl, 53495f757f3fSDimitry Andric SourceLocation(), SourceLocation(), II); 53500b57cec5SDimitry Andric assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); 53510b57cec5SDimitry Andric QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 53520b57cec5SDimitry Andric 53530b57cec5SDimitry Andric FD = SynthBlockInitFunctionDecl((*I)->getName()); 53540b57cec5SDimitry Andric Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(), 53550b57cec5SDimitry Andric VK_LValue, SourceLocation()); 53560b57cec5SDimitry Andric bool isNestedCapturedVar = false; 53570b57cec5SDimitry Andric for (const auto &CI : block->captures()) { 53580b57cec5SDimitry Andric const VarDecl *variable = CI.getVariable(); 53590b57cec5SDimitry Andric if (variable == ND && CI.isNested()) { 53600b57cec5SDimitry Andric assert(CI.isByRef() && 53610b57cec5SDimitry Andric "SynthBlockInitExpr - captured block variable is not byref"); 53620b57cec5SDimitry Andric isNestedCapturedVar = true; 53630b57cec5SDimitry Andric break; 53640b57cec5SDimitry Andric } 53650b57cec5SDimitry Andric } 53660b57cec5SDimitry Andric // captured nested byref variable has its address passed. Do not take 53670b57cec5SDimitry Andric // its address again. 53680b57cec5SDimitry Andric if (!isNestedCapturedVar) 53695ffd83dbSDimitry Andric Exp = UnaryOperator::Create( 53705ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), Exp, UO_AddrOf, 5371fe6060f1SDimitry Andric Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary, 53725ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 53730b57cec5SDimitry Andric Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); 53740b57cec5SDimitry Andric InitExprs.push_back(Exp); 53750b57cec5SDimitry Andric } 53760b57cec5SDimitry Andric } 53770b57cec5SDimitry Andric if (ImportedBlockDecls.size()) { 53780b57cec5SDimitry Andric // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR 53790b57cec5SDimitry Andric int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR); 53800b57cec5SDimitry Andric unsigned IntSize = 53810b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 53820b57cec5SDimitry Andric Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 53830b57cec5SDimitry Andric Context->IntTy, SourceLocation()); 53840b57cec5SDimitry Andric InitExprs.push_back(FlagExp); 53850b57cec5SDimitry Andric } 53860b57cec5SDimitry Andric NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue, 5387e8d8bef9SDimitry Andric SourceLocation(), FPOptionsOverride()); 53880b57cec5SDimitry Andric 53890b57cec5SDimitry Andric if (GlobalBlockExpr) { 53900b57cec5SDimitry Andric assert (!GlobalConstructionExp && 53910b57cec5SDimitry Andric "SynthBlockInitExpr - GlobalConstructionExp must be null"); 53920b57cec5SDimitry Andric GlobalConstructionExp = NewRep; 53930b57cec5SDimitry Andric NewRep = DRE; 53940b57cec5SDimitry Andric } 53950b57cec5SDimitry Andric 53965ffd83dbSDimitry Andric NewRep = UnaryOperator::Create( 53975ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf, 5398fe6060f1SDimitry Andric Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary, 53995ffd83dbSDimitry Andric SourceLocation(), false, FPOptionsOverride()); 54000b57cec5SDimitry Andric NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, 54010b57cec5SDimitry Andric NewRep); 54020b57cec5SDimitry Andric // Put Paren around the call. 54030b57cec5SDimitry Andric NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 54040b57cec5SDimitry Andric NewRep); 54050b57cec5SDimitry Andric 54060b57cec5SDimitry Andric BlockDeclRefs.clear(); 54070b57cec5SDimitry Andric BlockByRefDecls.clear(); 54080b57cec5SDimitry Andric BlockByRefDeclsPtrSet.clear(); 54090b57cec5SDimitry Andric BlockByCopyDecls.clear(); 54100b57cec5SDimitry Andric BlockByCopyDeclsPtrSet.clear(); 54110b57cec5SDimitry Andric ImportedBlockDecls.clear(); 54120b57cec5SDimitry Andric return NewRep; 54130b57cec5SDimitry Andric } 54140b57cec5SDimitry Andric 54150b57cec5SDimitry Andric bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { 54160b57cec5SDimitry Andric if (const ObjCForCollectionStmt * CS = 54170b57cec5SDimitry Andric dyn_cast<ObjCForCollectionStmt>(Stmts.back())) 54180b57cec5SDimitry Andric return CS->getElement() == DS; 54190b57cec5SDimitry Andric return false; 54200b57cec5SDimitry Andric } 54210b57cec5SDimitry Andric 54220b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 54230b57cec5SDimitry Andric // Function Body / Expression rewriting 54240b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 54250b57cec5SDimitry Andric 54260b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { 54270b57cec5SDimitry Andric if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 54280b57cec5SDimitry Andric isa<DoStmt>(S) || isa<ForStmt>(S)) 54290b57cec5SDimitry Andric Stmts.push_back(S); 54300b57cec5SDimitry Andric else if (isa<ObjCForCollectionStmt>(S)) { 54310b57cec5SDimitry Andric Stmts.push_back(S); 54320b57cec5SDimitry Andric ObjCBcLabelNo.push_back(++BcLabelCount); 54330b57cec5SDimitry Andric } 54340b57cec5SDimitry Andric 54350b57cec5SDimitry Andric // Pseudo-object operations and ivar references need special 54360b57cec5SDimitry Andric // treatment because we're going to recursively rewrite them. 54370b57cec5SDimitry Andric if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) { 54380b57cec5SDimitry Andric if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) { 54390b57cec5SDimitry Andric return RewritePropertyOrImplicitSetter(PseudoOp); 54400b57cec5SDimitry Andric } else { 54410b57cec5SDimitry Andric return RewritePropertyOrImplicitGetter(PseudoOp); 54420b57cec5SDimitry Andric } 54430b57cec5SDimitry Andric } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 54440b57cec5SDimitry Andric return RewriteObjCIvarRefExpr(IvarRefExpr); 54450b57cec5SDimitry Andric } 54460b57cec5SDimitry Andric else if (isa<OpaqueValueExpr>(S)) 54470b57cec5SDimitry Andric S = cast<OpaqueValueExpr>(S)->getSourceExpr(); 54480b57cec5SDimitry Andric 54490b57cec5SDimitry Andric SourceRange OrigStmtRange = S->getSourceRange(); 54500b57cec5SDimitry Andric 54510b57cec5SDimitry Andric // Perform a bottom up rewrite of all children. 54520b57cec5SDimitry Andric for (Stmt *&childStmt : S->children()) 54530b57cec5SDimitry Andric if (childStmt) { 54540b57cec5SDimitry Andric Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt); 54550b57cec5SDimitry Andric if (newStmt) { 54560b57cec5SDimitry Andric childStmt = newStmt; 54570b57cec5SDimitry Andric } 54580b57cec5SDimitry Andric } 54590b57cec5SDimitry Andric 54600b57cec5SDimitry Andric if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { 54610b57cec5SDimitry Andric SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs; 54620b57cec5SDimitry Andric llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; 54630b57cec5SDimitry Andric InnerContexts.insert(BE->getBlockDecl()); 54640b57cec5SDimitry Andric ImportedLocalExternalDecls.clear(); 54650b57cec5SDimitry Andric GetInnerBlockDeclRefExprs(BE->getBody(), 54660b57cec5SDimitry Andric InnerBlockDeclRefs, InnerContexts); 54670b57cec5SDimitry Andric // Rewrite the block body in place. 54680b57cec5SDimitry Andric Stmt *SaveCurrentBody = CurrentBody; 54690b57cec5SDimitry Andric CurrentBody = BE->getBody(); 54700b57cec5SDimitry Andric PropParentMap = nullptr; 54710b57cec5SDimitry Andric // block literal on rhs of a property-dot-sytax assignment 54720b57cec5SDimitry Andric // must be replaced by its synthesize ast so getRewrittenText 54730b57cec5SDimitry Andric // works as expected. In this case, what actually ends up on RHS 54740b57cec5SDimitry Andric // is the blockTranscribed which is the helper function for the 54750b57cec5SDimitry Andric // block literal; as in: self.c = ^() {[ace ARR];}; 54760b57cec5SDimitry Andric bool saveDisableReplaceStmt = DisableReplaceStmt; 54770b57cec5SDimitry Andric DisableReplaceStmt = false; 54780b57cec5SDimitry Andric RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); 54790b57cec5SDimitry Andric DisableReplaceStmt = saveDisableReplaceStmt; 54800b57cec5SDimitry Andric CurrentBody = SaveCurrentBody; 54810b57cec5SDimitry Andric PropParentMap = nullptr; 54820b57cec5SDimitry Andric ImportedLocalExternalDecls.clear(); 54830b57cec5SDimitry Andric // Now we snarf the rewritten text and stash it away for later use. 54840b57cec5SDimitry Andric std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); 54850b57cec5SDimitry Andric RewrittenBlockExprs[BE] = Str; 54860b57cec5SDimitry Andric 54870b57cec5SDimitry Andric Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); 54880b57cec5SDimitry Andric 54890b57cec5SDimitry Andric //blockTranscribed->dump(); 54900b57cec5SDimitry Andric ReplaceStmt(S, blockTranscribed); 54910b57cec5SDimitry Andric return blockTranscribed; 54920b57cec5SDimitry Andric } 54930b57cec5SDimitry Andric // Handle specific things. 54940b57cec5SDimitry Andric if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) 54950b57cec5SDimitry Andric return RewriteAtEncode(AtEncode); 54960b57cec5SDimitry Andric 54970b57cec5SDimitry Andric if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) 54980b57cec5SDimitry Andric return RewriteAtSelector(AtSelector); 54990b57cec5SDimitry Andric 55000b57cec5SDimitry Andric if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) 55010b57cec5SDimitry Andric return RewriteObjCStringLiteral(AtString); 55020b57cec5SDimitry Andric 55030b57cec5SDimitry Andric if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S)) 55040b57cec5SDimitry Andric return RewriteObjCBoolLiteralExpr(BoolLitExpr); 55050b57cec5SDimitry Andric 55060b57cec5SDimitry Andric if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S)) 55070b57cec5SDimitry Andric return RewriteObjCBoxedExpr(BoxedExpr); 55080b57cec5SDimitry Andric 55090b57cec5SDimitry Andric if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S)) 55100b57cec5SDimitry Andric return RewriteObjCArrayLiteralExpr(ArrayLitExpr); 55110b57cec5SDimitry Andric 55120b57cec5SDimitry Andric if (ObjCDictionaryLiteral *DictionaryLitExpr = 55130b57cec5SDimitry Andric dyn_cast<ObjCDictionaryLiteral>(S)) 55140b57cec5SDimitry Andric return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr); 55150b57cec5SDimitry Andric 55160b57cec5SDimitry Andric if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { 55170b57cec5SDimitry Andric #if 0 55180b57cec5SDimitry Andric // Before we rewrite it, put the original message expression in a comment. 55190b57cec5SDimitry Andric SourceLocation startLoc = MessExpr->getBeginLoc(); 55200b57cec5SDimitry Andric SourceLocation endLoc = MessExpr->getEndLoc(); 55210b57cec5SDimitry Andric 55220b57cec5SDimitry Andric const char *startBuf = SM->getCharacterData(startLoc); 55230b57cec5SDimitry Andric const char *endBuf = SM->getCharacterData(endLoc); 55240b57cec5SDimitry Andric 55250b57cec5SDimitry Andric std::string messString; 55260b57cec5SDimitry Andric messString += "// "; 55270b57cec5SDimitry Andric messString.append(startBuf, endBuf-startBuf+1); 55280b57cec5SDimitry Andric messString += "\n"; 55290b57cec5SDimitry Andric 55300b57cec5SDimitry Andric // FIXME: Missing definition of 55310b57cec5SDimitry Andric // InsertText(clang::SourceLocation, char const*, unsigned int). 55320b57cec5SDimitry Andric // InsertText(startLoc, messString); 55330b57cec5SDimitry Andric // Tried this, but it didn't work either... 55340b57cec5SDimitry Andric // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); 55350b57cec5SDimitry Andric #endif 55360b57cec5SDimitry Andric return RewriteMessageExpr(MessExpr); 55370b57cec5SDimitry Andric } 55380b57cec5SDimitry Andric 55390b57cec5SDimitry Andric if (ObjCAutoreleasePoolStmt *StmtAutoRelease = 55400b57cec5SDimitry Andric dyn_cast<ObjCAutoreleasePoolStmt>(S)) { 55410b57cec5SDimitry Andric return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease); 55420b57cec5SDimitry Andric } 55430b57cec5SDimitry Andric 55440b57cec5SDimitry Andric if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) 55450b57cec5SDimitry Andric return RewriteObjCTryStmt(StmtTry); 55460b57cec5SDimitry Andric 55470b57cec5SDimitry Andric if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) 55480b57cec5SDimitry Andric return RewriteObjCSynchronizedStmt(StmtTry); 55490b57cec5SDimitry Andric 55500b57cec5SDimitry Andric if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) 55510b57cec5SDimitry Andric return RewriteObjCThrowStmt(StmtThrow); 55520b57cec5SDimitry Andric 55530b57cec5SDimitry Andric if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) 55540b57cec5SDimitry Andric return RewriteObjCProtocolExpr(ProtocolExp); 55550b57cec5SDimitry Andric 55560b57cec5SDimitry Andric if (ObjCForCollectionStmt *StmtForCollection = 55570b57cec5SDimitry Andric dyn_cast<ObjCForCollectionStmt>(S)) 55580b57cec5SDimitry Andric return RewriteObjCForCollectionStmt(StmtForCollection, 55590b57cec5SDimitry Andric OrigStmtRange.getEnd()); 55600b57cec5SDimitry Andric if (BreakStmt *StmtBreakStmt = 55610b57cec5SDimitry Andric dyn_cast<BreakStmt>(S)) 55620b57cec5SDimitry Andric return RewriteBreakStmt(StmtBreakStmt); 55630b57cec5SDimitry Andric if (ContinueStmt *StmtContinueStmt = 55640b57cec5SDimitry Andric dyn_cast<ContinueStmt>(S)) 55650b57cec5SDimitry Andric return RewriteContinueStmt(StmtContinueStmt); 55660b57cec5SDimitry Andric 55670b57cec5SDimitry Andric // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls 55680b57cec5SDimitry Andric // and cast exprs. 55690b57cec5SDimitry Andric if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 55700b57cec5SDimitry Andric // FIXME: What we're doing here is modifying the type-specifier that 55710b57cec5SDimitry Andric // precedes the first Decl. In the future the DeclGroup should have 55720b57cec5SDimitry Andric // a separate type-specifier that we can rewrite. 55730b57cec5SDimitry Andric // NOTE: We need to avoid rewriting the DeclStmt if it is within 55740b57cec5SDimitry Andric // the context of an ObjCForCollectionStmt. For example: 55750b57cec5SDimitry Andric // NSArray *someArray; 55760b57cec5SDimitry Andric // for (id <FooProtocol> index in someArray) ; 55770b57cec5SDimitry Andric // This is because RewriteObjCForCollectionStmt() does textual rewriting 55780b57cec5SDimitry Andric // and it depends on the original text locations/positions. 55790b57cec5SDimitry Andric if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS)) 55800b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); 55810b57cec5SDimitry Andric 55820b57cec5SDimitry Andric // Blocks rewrite rules. 55830b57cec5SDimitry Andric for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 55840b57cec5SDimitry Andric DI != DE; ++DI) { 55850b57cec5SDimitry Andric Decl *SD = *DI; 55860b57cec5SDimitry Andric if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { 55870b57cec5SDimitry Andric if (isTopLevelBlockPointerType(ND->getType())) 55880b57cec5SDimitry Andric RewriteBlockPointerDecl(ND); 55890b57cec5SDimitry Andric else if (ND->getType()->isFunctionPointerType()) 55900b57cec5SDimitry Andric CheckFunctionPointerDecl(ND->getType(), ND); 55910b57cec5SDimitry Andric if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { 55920b57cec5SDimitry Andric if (VD->hasAttr<BlocksAttr>()) { 55930b57cec5SDimitry Andric static unsigned uniqueByrefDeclCount = 0; 55940b57cec5SDimitry Andric assert(!BlockByRefDeclNo.count(ND) && 55950b57cec5SDimitry Andric "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); 55960b57cec5SDimitry Andric BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; 55970b57cec5SDimitry Andric RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE)); 55980b57cec5SDimitry Andric } 55990b57cec5SDimitry Andric else 56000b57cec5SDimitry Andric RewriteTypeOfDecl(VD); 56010b57cec5SDimitry Andric } 56020b57cec5SDimitry Andric } 56030b57cec5SDimitry Andric if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { 56040b57cec5SDimitry Andric if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 56050b57cec5SDimitry Andric RewriteBlockPointerDecl(TD); 56060b57cec5SDimitry Andric else if (TD->getUnderlyingType()->isFunctionPointerType()) 56070b57cec5SDimitry Andric CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 56080b57cec5SDimitry Andric } 56090b57cec5SDimitry Andric } 56100b57cec5SDimitry Andric } 56110b57cec5SDimitry Andric 56120b57cec5SDimitry Andric if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) 56130b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(CE); 56140b57cec5SDimitry Andric 56150b57cec5SDimitry Andric if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 56160b57cec5SDimitry Andric isa<DoStmt>(S) || isa<ForStmt>(S)) { 56170b57cec5SDimitry Andric assert(!Stmts.empty() && "Statement stack is empty"); 56180b57cec5SDimitry Andric assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 56190b57cec5SDimitry Andric isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 56200b57cec5SDimitry Andric && "Statement stack mismatch"); 56210b57cec5SDimitry Andric Stmts.pop_back(); 56220b57cec5SDimitry Andric } 56230b57cec5SDimitry Andric // Handle blocks rewriting. 56240b57cec5SDimitry Andric if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 56250b57cec5SDimitry Andric ValueDecl *VD = DRE->getDecl(); 56260b57cec5SDimitry Andric if (VD->hasAttr<BlocksAttr>()) 56270b57cec5SDimitry Andric return RewriteBlockDeclRefExpr(DRE); 56280b57cec5SDimitry Andric if (HasLocalVariableExternalStorage(VD)) 56290b57cec5SDimitry Andric return RewriteLocalVariableExternalStorage(DRE); 56300b57cec5SDimitry Andric } 56310b57cec5SDimitry Andric 56320b57cec5SDimitry Andric if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 56330b57cec5SDimitry Andric if (CE->getCallee()->getType()->isBlockPointerType()) { 56340b57cec5SDimitry Andric Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); 56350b57cec5SDimitry Andric ReplaceStmt(S, BlockCall); 56360b57cec5SDimitry Andric return BlockCall; 56370b57cec5SDimitry Andric } 56380b57cec5SDimitry Andric } 56390b57cec5SDimitry Andric if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) { 56400b57cec5SDimitry Andric RewriteCastExpr(CE); 56410b57cec5SDimitry Andric } 56420b57cec5SDimitry Andric if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 56430b57cec5SDimitry Andric RewriteImplicitCastObjCExpr(ICE); 56440b57cec5SDimitry Andric } 56450b57cec5SDimitry Andric #if 0 56460b57cec5SDimitry Andric 56470b57cec5SDimitry Andric if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 56480b57cec5SDimitry Andric CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), 56490b57cec5SDimitry Andric ICE->getSubExpr(), 56500b57cec5SDimitry Andric SourceLocation()); 56510b57cec5SDimitry Andric // Get the new text. 56520b57cec5SDimitry Andric std::string SStr; 56530b57cec5SDimitry Andric llvm::raw_string_ostream Buf(SStr); 56540b57cec5SDimitry Andric Replacement->printPretty(Buf); 56550b57cec5SDimitry Andric const std::string &Str = Buf.str(); 56560b57cec5SDimitry Andric 56570b57cec5SDimitry Andric printf("CAST = %s\n", &Str[0]); 56580b57cec5SDimitry Andric InsertText(ICE->getSubExpr()->getBeginLoc(), Str); 56590b57cec5SDimitry Andric delete S; 56600b57cec5SDimitry Andric return Replacement; 56610b57cec5SDimitry Andric } 56620b57cec5SDimitry Andric #endif 56630b57cec5SDimitry Andric // Return this stmt unmodified. 56640b57cec5SDimitry Andric return S; 56650b57cec5SDimitry Andric } 56660b57cec5SDimitry Andric 56670b57cec5SDimitry Andric void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) { 56680b57cec5SDimitry Andric for (auto *FD : RD->fields()) { 56690b57cec5SDimitry Andric if (isTopLevelBlockPointerType(FD->getType())) 56700b57cec5SDimitry Andric RewriteBlockPointerDecl(FD); 56710b57cec5SDimitry Andric if (FD->getType()->isObjCQualifiedIdType() || 56720b57cec5SDimitry Andric FD->getType()->isObjCQualifiedInterfaceType()) 56730b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(FD); 56740b57cec5SDimitry Andric } 56750b57cec5SDimitry Andric } 56760b57cec5SDimitry Andric 56770b57cec5SDimitry Andric /// HandleDeclInMainFile - This is called for each top-level decl defined in the 56780b57cec5SDimitry Andric /// main file of the input. 56790b57cec5SDimitry Andric void RewriteModernObjC::HandleDeclInMainFile(Decl *D) { 56800b57cec5SDimitry Andric switch (D->getKind()) { 56810b57cec5SDimitry Andric case Decl::Function: { 56820b57cec5SDimitry Andric FunctionDecl *FD = cast<FunctionDecl>(D); 56830b57cec5SDimitry Andric if (FD->isOverloadedOperator()) 56840b57cec5SDimitry Andric return; 56850b57cec5SDimitry Andric 56860b57cec5SDimitry Andric // Since function prototypes don't have ParmDecl's, we check the function 56870b57cec5SDimitry Andric // prototype. This enables us to rewrite function declarations and 56880b57cec5SDimitry Andric // definitions using the same code. 56890b57cec5SDimitry Andric RewriteBlocksInFunctionProtoType(FD->getType(), FD); 56900b57cec5SDimitry Andric 56910b57cec5SDimitry Andric if (!FD->isThisDeclarationADefinition()) 56920b57cec5SDimitry Andric break; 56930b57cec5SDimitry Andric 56940b57cec5SDimitry Andric // FIXME: If this should support Obj-C++, support CXXTryStmt 56950b57cec5SDimitry Andric if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { 56960b57cec5SDimitry Andric CurFunctionDef = FD; 56970b57cec5SDimitry Andric CurrentBody = Body; 56980b57cec5SDimitry Andric Body = 56990b57cec5SDimitry Andric cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 57000b57cec5SDimitry Andric FD->setBody(Body); 57010b57cec5SDimitry Andric CurrentBody = nullptr; 57020b57cec5SDimitry Andric if (PropParentMap) { 57030b57cec5SDimitry Andric delete PropParentMap; 57040b57cec5SDimitry Andric PropParentMap = nullptr; 57050b57cec5SDimitry Andric } 57060b57cec5SDimitry Andric // This synthesizes and inserts the block "impl" struct, invoke function, 57070b57cec5SDimitry Andric // and any copy/dispose helper functions. 57080b57cec5SDimitry Andric InsertBlockLiteralsWithinFunction(FD); 57090b57cec5SDimitry Andric RewriteLineDirective(D); 57100b57cec5SDimitry Andric CurFunctionDef = nullptr; 57110b57cec5SDimitry Andric } 57120b57cec5SDimitry Andric break; 57130b57cec5SDimitry Andric } 57140b57cec5SDimitry Andric case Decl::ObjCMethod: { 57150b57cec5SDimitry Andric ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); 57160b57cec5SDimitry Andric if (CompoundStmt *Body = MD->getCompoundBody()) { 57170b57cec5SDimitry Andric CurMethodDef = MD; 57180b57cec5SDimitry Andric CurrentBody = Body; 57190b57cec5SDimitry Andric Body = 57200b57cec5SDimitry Andric cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 57210b57cec5SDimitry Andric MD->setBody(Body); 57220b57cec5SDimitry Andric CurrentBody = nullptr; 57230b57cec5SDimitry Andric if (PropParentMap) { 57240b57cec5SDimitry Andric delete PropParentMap; 57250b57cec5SDimitry Andric PropParentMap = nullptr; 57260b57cec5SDimitry Andric } 57270b57cec5SDimitry Andric InsertBlockLiteralsWithinMethod(MD); 57280b57cec5SDimitry Andric RewriteLineDirective(D); 57290b57cec5SDimitry Andric CurMethodDef = nullptr; 57300b57cec5SDimitry Andric } 57310b57cec5SDimitry Andric break; 57320b57cec5SDimitry Andric } 57330b57cec5SDimitry Andric case Decl::ObjCImplementation: { 57340b57cec5SDimitry Andric ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D); 57350b57cec5SDimitry Andric ClassImplementation.push_back(CI); 57360b57cec5SDimitry Andric break; 57370b57cec5SDimitry Andric } 57380b57cec5SDimitry Andric case Decl::ObjCCategoryImpl: { 57390b57cec5SDimitry Andric ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D); 57400b57cec5SDimitry Andric CategoryImplementation.push_back(CI); 57410b57cec5SDimitry Andric break; 57420b57cec5SDimitry Andric } 57430b57cec5SDimitry Andric case Decl::Var: { 57440b57cec5SDimitry Andric VarDecl *VD = cast<VarDecl>(D); 57450b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(VD); 57460b57cec5SDimitry Andric if (isTopLevelBlockPointerType(VD->getType())) 57470b57cec5SDimitry Andric RewriteBlockPointerDecl(VD); 57480b57cec5SDimitry Andric else if (VD->getType()->isFunctionPointerType()) { 57490b57cec5SDimitry Andric CheckFunctionPointerDecl(VD->getType(), VD); 57500b57cec5SDimitry Andric if (VD->getInit()) { 57510b57cec5SDimitry Andric if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 57520b57cec5SDimitry Andric RewriteCastExpr(CE); 57530b57cec5SDimitry Andric } 57540b57cec5SDimitry Andric } 57550b57cec5SDimitry Andric } else if (VD->getType()->isRecordType()) { 5756a7dea167SDimitry Andric RecordDecl *RD = VD->getType()->castAs<RecordType>()->getDecl(); 57570b57cec5SDimitry Andric if (RD->isCompleteDefinition()) 57580b57cec5SDimitry Andric RewriteRecordBody(RD); 57590b57cec5SDimitry Andric } 57600b57cec5SDimitry Andric if (VD->getInit()) { 57610b57cec5SDimitry Andric GlobalVarDecl = VD; 57620b57cec5SDimitry Andric CurrentBody = VD->getInit(); 57630b57cec5SDimitry Andric RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); 57640b57cec5SDimitry Andric CurrentBody = nullptr; 57650b57cec5SDimitry Andric if (PropParentMap) { 57660b57cec5SDimitry Andric delete PropParentMap; 57670b57cec5SDimitry Andric PropParentMap = nullptr; 57680b57cec5SDimitry Andric } 57690b57cec5SDimitry Andric SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName()); 57700b57cec5SDimitry Andric GlobalVarDecl = nullptr; 57710b57cec5SDimitry Andric 57720b57cec5SDimitry Andric // This is needed for blocks. 57730b57cec5SDimitry Andric if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 57740b57cec5SDimitry Andric RewriteCastExpr(CE); 57750b57cec5SDimitry Andric } 57760b57cec5SDimitry Andric } 57770b57cec5SDimitry Andric break; 57780b57cec5SDimitry Andric } 57790b57cec5SDimitry Andric case Decl::TypeAlias: 57800b57cec5SDimitry Andric case Decl::Typedef: { 57810b57cec5SDimitry Andric if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 57820b57cec5SDimitry Andric if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 57830b57cec5SDimitry Andric RewriteBlockPointerDecl(TD); 57840b57cec5SDimitry Andric else if (TD->getUnderlyingType()->isFunctionPointerType()) 57850b57cec5SDimitry Andric CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 57860b57cec5SDimitry Andric else 57870b57cec5SDimitry Andric RewriteObjCQualifiedInterfaceTypes(TD); 57880b57cec5SDimitry Andric } 57890b57cec5SDimitry Andric break; 57900b57cec5SDimitry Andric } 57910b57cec5SDimitry Andric case Decl::CXXRecord: 57920b57cec5SDimitry Andric case Decl::Record: { 57930b57cec5SDimitry Andric RecordDecl *RD = cast<RecordDecl>(D); 57940b57cec5SDimitry Andric if (RD->isCompleteDefinition()) 57950b57cec5SDimitry Andric RewriteRecordBody(RD); 57960b57cec5SDimitry Andric break; 57970b57cec5SDimitry Andric } 57980b57cec5SDimitry Andric default: 57990b57cec5SDimitry Andric break; 58000b57cec5SDimitry Andric } 58010b57cec5SDimitry Andric // Nothing yet. 58020b57cec5SDimitry Andric } 58030b57cec5SDimitry Andric 58040b57cec5SDimitry Andric /// Write_ProtocolExprReferencedMetadata - This routine writer out the 58050b57cec5SDimitry Andric /// protocol reference symbols in the for of: 58060b57cec5SDimitry Andric /// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA. 58070b57cec5SDimitry Andric static void Write_ProtocolExprReferencedMetadata(ASTContext *Context, 58080b57cec5SDimitry Andric ObjCProtocolDecl *PDecl, 58090b57cec5SDimitry Andric std::string &Result) { 58100b57cec5SDimitry Andric // Also output .objc_protorefs$B section and its meta-data. 58110b57cec5SDimitry Andric if (Context->getLangOpts().MicrosoftExt) 58120b57cec5SDimitry Andric Result += "static "; 58130b57cec5SDimitry Andric Result += "struct _protocol_t *"; 58140b57cec5SDimitry Andric Result += "_OBJC_PROTOCOL_REFERENCE_$_"; 58150b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 58160b57cec5SDimitry Andric Result += " = &"; 58170b57cec5SDimitry Andric Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString(); 58180b57cec5SDimitry Andric Result += ";\n"; 58190b57cec5SDimitry Andric } 58200b57cec5SDimitry Andric 58210b57cec5SDimitry Andric void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) { 58220b57cec5SDimitry Andric if (Diags.hasErrorOccurred()) 58230b57cec5SDimitry Andric return; 58240b57cec5SDimitry Andric 58250b57cec5SDimitry Andric RewriteInclude(); 58260b57cec5SDimitry Andric 58270b57cec5SDimitry Andric for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) { 58280b57cec5SDimitry Andric // translation of function bodies were postponed until all class and 58290b57cec5SDimitry Andric // their extensions and implementations are seen. This is because, we 58300b57cec5SDimitry Andric // cannot build grouping structs for bitfields until they are all seen. 58310b57cec5SDimitry Andric FunctionDecl *FDecl = FunctionDefinitionsSeen[i]; 58320b57cec5SDimitry Andric HandleTopLevelSingleDecl(FDecl); 58330b57cec5SDimitry Andric } 58340b57cec5SDimitry Andric 58350b57cec5SDimitry Andric // Here's a great place to add any extra declarations that may be needed. 58360b57cec5SDimitry Andric // Write out meta data for each @protocol(<expr>). 58370b57cec5SDimitry Andric for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) { 58380b57cec5SDimitry Andric RewriteObjCProtocolMetaData(ProtDecl, Preamble); 58390b57cec5SDimitry Andric Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble); 58400b57cec5SDimitry Andric } 58410b57cec5SDimitry Andric 58420b57cec5SDimitry Andric InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); 58430b57cec5SDimitry Andric 58440b57cec5SDimitry Andric if (ClassImplementation.size() || CategoryImplementation.size()) 58450b57cec5SDimitry Andric RewriteImplementations(); 58460b57cec5SDimitry Andric 58470b57cec5SDimitry Andric for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) { 58480b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i]; 58490b57cec5SDimitry Andric // Write struct declaration for the class matching its ivar declarations. 58500b57cec5SDimitry Andric // Note that for modern abi, this is postponed until the end of TU 58510b57cec5SDimitry Andric // because class extensions and the implementation might declare their own 58520b57cec5SDimitry Andric // private ivars. 58530b57cec5SDimitry Andric RewriteInterfaceDecl(CDecl); 58540b57cec5SDimitry Andric } 58550b57cec5SDimitry Andric 58560b57cec5SDimitry Andric // Get the buffer corresponding to MainFileID. If we haven't changed it, then 58570b57cec5SDimitry Andric // we are done. 58580b57cec5SDimitry Andric if (const RewriteBuffer *RewriteBuf = 58590b57cec5SDimitry Andric Rewrite.getRewriteBufferFor(MainFileID)) { 58600b57cec5SDimitry Andric //printf("Changed:\n"); 58610b57cec5SDimitry Andric *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 58620b57cec5SDimitry Andric } else { 58630b57cec5SDimitry Andric llvm::errs() << "No changes\n"; 58640b57cec5SDimitry Andric } 58650b57cec5SDimitry Andric 58660b57cec5SDimitry Andric if (ClassImplementation.size() || CategoryImplementation.size() || 58670b57cec5SDimitry Andric ProtocolExprDecls.size()) { 58680b57cec5SDimitry Andric // Rewrite Objective-c meta data* 58690b57cec5SDimitry Andric std::string ResultStr; 58700b57cec5SDimitry Andric RewriteMetaDataIntoBuffer(ResultStr); 58710b57cec5SDimitry Andric // Emit metadata. 58720b57cec5SDimitry Andric *OutFile << ResultStr; 58730b57cec5SDimitry Andric } 58740b57cec5SDimitry Andric // Emit ImageInfo; 58750b57cec5SDimitry Andric { 58760b57cec5SDimitry Andric std::string ResultStr; 58770b57cec5SDimitry Andric WriteImageInfo(ResultStr); 58780b57cec5SDimitry Andric *OutFile << ResultStr; 58790b57cec5SDimitry Andric } 58800b57cec5SDimitry Andric OutFile->flush(); 58810b57cec5SDimitry Andric } 58820b57cec5SDimitry Andric 58830b57cec5SDimitry Andric void RewriteModernObjC::Initialize(ASTContext &context) { 58840b57cec5SDimitry Andric InitializeCommon(context); 58850b57cec5SDimitry Andric 58860b57cec5SDimitry Andric Preamble += "#ifndef __OBJC2__\n"; 58870b57cec5SDimitry Andric Preamble += "#define __OBJC2__\n"; 58880b57cec5SDimitry Andric Preamble += "#endif\n"; 58890b57cec5SDimitry Andric 58900b57cec5SDimitry Andric // declaring objc_selector outside the parameter list removes a silly 58910b57cec5SDimitry Andric // scope related warning... 58920b57cec5SDimitry Andric if (IsHeader) 58930b57cec5SDimitry Andric Preamble = "#pragma once\n"; 58940b57cec5SDimitry Andric Preamble += "struct objc_selector; struct objc_class;\n"; 58950b57cec5SDimitry Andric Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; "; 58960b57cec5SDimitry Andric Preamble += "\n\tstruct objc_object *superClass; "; 58970b57cec5SDimitry Andric // Add a constructor for creating temporary objects. 58980b57cec5SDimitry Andric Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) "; 58990b57cec5SDimitry Andric Preamble += ": object(o), superClass(s) {} "; 59000b57cec5SDimitry Andric Preamble += "\n};\n"; 59010b57cec5SDimitry Andric 59020b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 59030b57cec5SDimitry Andric // Define all sections using syntax that makes sense. 59040b57cec5SDimitry Andric // These are currently generated. 59050b57cec5SDimitry Andric Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n"; 59060b57cec5SDimitry Andric Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n"; 59070b57cec5SDimitry Andric Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n"; 59080b57cec5SDimitry Andric Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n"; 59090b57cec5SDimitry Andric Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n"; 59100b57cec5SDimitry Andric // These are generated but not necessary for functionality. 59110b57cec5SDimitry Andric Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n"; 59120b57cec5SDimitry Andric Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n"; 59130b57cec5SDimitry Andric Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n"; 59140b57cec5SDimitry Andric Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n"; 59150b57cec5SDimitry Andric 59160b57cec5SDimitry Andric // These need be generated for performance. Currently they are not, 59170b57cec5SDimitry Andric // using API calls instead. 59180b57cec5SDimitry Andric Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n"; 59190b57cec5SDimitry Andric Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n"; 59200b57cec5SDimitry Andric Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n"; 59210b57cec5SDimitry Andric 59220b57cec5SDimitry Andric } 59230b57cec5SDimitry Andric Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; 59240b57cec5SDimitry Andric Preamble += "typedef struct objc_object Protocol;\n"; 59250b57cec5SDimitry Andric Preamble += "#define _REWRITER_typedef_Protocol\n"; 59260b57cec5SDimitry Andric Preamble += "#endif\n"; 59270b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 59280b57cec5SDimitry Andric Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; 59290b57cec5SDimitry Andric Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; 59300b57cec5SDimitry Andric } 59310b57cec5SDimitry Andric else 59320b57cec5SDimitry Andric Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; 59330b57cec5SDimitry Andric 59340b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n"; 59350b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n"; 59360b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n"; 59370b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n"; 59380b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n"; 59390b57cec5SDimitry Andric 59400b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass"; 59410b57cec5SDimitry Andric Preamble += "(const char *);\n"; 59420b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; 59430b57cec5SDimitry Andric Preamble += "(struct objc_class *);\n"; 59440b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass"; 59450b57cec5SDimitry Andric Preamble += "(const char *);\n"; 59460b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n"; 59470b57cec5SDimitry Andric // @synchronized hooks. 59480b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n"; 59490b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n"; 59500b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; 59510b57cec5SDimitry Andric Preamble += "#ifdef _WIN64\n"; 59520b57cec5SDimitry Andric Preamble += "typedef unsigned long long _WIN_NSUInteger;\n"; 59530b57cec5SDimitry Andric Preamble += "#else\n"; 59540b57cec5SDimitry Andric Preamble += "typedef unsigned int _WIN_NSUInteger;\n"; 59550b57cec5SDimitry Andric Preamble += "#endif\n"; 59560b57cec5SDimitry Andric Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; 59570b57cec5SDimitry Andric Preamble += "struct __objcFastEnumerationState {\n\t"; 59580b57cec5SDimitry Andric Preamble += "unsigned long state;\n\t"; 59590b57cec5SDimitry Andric Preamble += "void **itemsPtr;\n\t"; 59600b57cec5SDimitry Andric Preamble += "unsigned long *mutationsPtr;\n\t"; 59610b57cec5SDimitry Andric Preamble += "unsigned long extra[5];\n};\n"; 59620b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; 59630b57cec5SDimitry Andric Preamble += "#define __FASTENUMERATIONSTATE\n"; 59640b57cec5SDimitry Andric Preamble += "#endif\n"; 59650b57cec5SDimitry Andric Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; 59660b57cec5SDimitry Andric Preamble += "struct __NSConstantStringImpl {\n"; 59670b57cec5SDimitry Andric Preamble += " int *isa;\n"; 59680b57cec5SDimitry Andric Preamble += " int flags;\n"; 59690b57cec5SDimitry Andric Preamble += " char *str;\n"; 59700b57cec5SDimitry Andric Preamble += "#if _WIN64\n"; 59710b57cec5SDimitry Andric Preamble += " long long length;\n"; 59720b57cec5SDimitry Andric Preamble += "#else\n"; 59730b57cec5SDimitry Andric Preamble += " long length;\n"; 59740b57cec5SDimitry Andric Preamble += "#endif\n"; 59750b57cec5SDimitry Andric Preamble += "};\n"; 59760b57cec5SDimitry Andric Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; 59770b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; 59780b57cec5SDimitry Andric Preamble += "#else\n"; 59790b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; 59800b57cec5SDimitry Andric Preamble += "#endif\n"; 59810b57cec5SDimitry Andric Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; 59820b57cec5SDimitry Andric Preamble += "#endif\n"; 59830b57cec5SDimitry Andric // Blocks preamble. 59840b57cec5SDimitry Andric Preamble += "#ifndef BLOCK_IMPL\n"; 59850b57cec5SDimitry Andric Preamble += "#define BLOCK_IMPL\n"; 59860b57cec5SDimitry Andric Preamble += "struct __block_impl {\n"; 59870b57cec5SDimitry Andric Preamble += " void *isa;\n"; 59880b57cec5SDimitry Andric Preamble += " int Flags;\n"; 59890b57cec5SDimitry Andric Preamble += " int Reserved;\n"; 59900b57cec5SDimitry Andric Preamble += " void *FuncPtr;\n"; 59910b57cec5SDimitry Andric Preamble += "};\n"; 59920b57cec5SDimitry Andric Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; 59930b57cec5SDimitry Andric Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; 59940b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) " 59950b57cec5SDimitry Andric "void _Block_object_assign(void *, const void *, const int);\n"; 59960b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; 59970b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; 59980b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; 59990b57cec5SDimitry Andric Preamble += "#else\n"; 60000b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; 60010b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; 60020b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; 60030b57cec5SDimitry Andric Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; 60040b57cec5SDimitry Andric Preamble += "#endif\n"; 60050b57cec5SDimitry Andric Preamble += "#endif\n"; 60060b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 60070b57cec5SDimitry Andric Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; 60080b57cec5SDimitry Andric Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; 60090b57cec5SDimitry Andric Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. 60100b57cec5SDimitry Andric Preamble += "#define __attribute__(X)\n"; 60110b57cec5SDimitry Andric Preamble += "#endif\n"; 60120b57cec5SDimitry Andric Preamble += "#ifndef __weak\n"; 60130b57cec5SDimitry Andric Preamble += "#define __weak\n"; 60140b57cec5SDimitry Andric Preamble += "#endif\n"; 60150b57cec5SDimitry Andric Preamble += "#ifndef __block\n"; 60160b57cec5SDimitry Andric Preamble += "#define __block\n"; 60170b57cec5SDimitry Andric Preamble += "#endif\n"; 60180b57cec5SDimitry Andric } 60190b57cec5SDimitry Andric else { 60200b57cec5SDimitry Andric Preamble += "#define __block\n"; 60210b57cec5SDimitry Andric Preamble += "#define __weak\n"; 60220b57cec5SDimitry Andric } 60230b57cec5SDimitry Andric 60240b57cec5SDimitry Andric // Declarations required for modern objective-c array and dictionary literals. 60250b57cec5SDimitry Andric Preamble += "\n#include <stdarg.h>\n"; 60260b57cec5SDimitry Andric Preamble += "struct __NSContainer_literal {\n"; 60270b57cec5SDimitry Andric Preamble += " void * *arr;\n"; 60280b57cec5SDimitry Andric Preamble += " __NSContainer_literal (unsigned int count, ...) {\n"; 60290b57cec5SDimitry Andric Preamble += "\tva_list marker;\n"; 60300b57cec5SDimitry Andric Preamble += "\tva_start(marker, count);\n"; 60310b57cec5SDimitry Andric Preamble += "\tarr = new void *[count];\n"; 60320b57cec5SDimitry Andric Preamble += "\tfor (unsigned i = 0; i < count; i++)\n"; 60330b57cec5SDimitry Andric Preamble += "\t arr[i] = va_arg(marker, void *);\n"; 60340b57cec5SDimitry Andric Preamble += "\tva_end( marker );\n"; 60350b57cec5SDimitry Andric Preamble += " };\n"; 60360b57cec5SDimitry Andric Preamble += " ~__NSContainer_literal() {\n"; 60370b57cec5SDimitry Andric Preamble += "\tdelete[] arr;\n"; 60380b57cec5SDimitry Andric Preamble += " }\n"; 60390b57cec5SDimitry Andric Preamble += "};\n"; 60400b57cec5SDimitry Andric 60410b57cec5SDimitry Andric // Declaration required for implementation of @autoreleasepool statement. 60420b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n"; 60430b57cec5SDimitry Andric Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n"; 60440b57cec5SDimitry Andric Preamble += "struct __AtAutoreleasePool {\n"; 60450b57cec5SDimitry Andric Preamble += " __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n"; 60460b57cec5SDimitry Andric Preamble += " ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n"; 60470b57cec5SDimitry Andric Preamble += " void * atautoreleasepoolobj;\n"; 60480b57cec5SDimitry Andric Preamble += "};\n"; 60490b57cec5SDimitry Andric 60500b57cec5SDimitry Andric // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long 60510b57cec5SDimitry Andric // as this avoids warning in any 64bit/32bit compilation model. 60520b57cec5SDimitry Andric Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; 60530b57cec5SDimitry Andric } 60540b57cec5SDimitry Andric 60550b57cec5SDimitry Andric /// RewriteIvarOffsetComputation - This routine synthesizes computation of 60560b57cec5SDimitry Andric /// ivar offset. 60570b57cec5SDimitry Andric void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 60580b57cec5SDimitry Andric std::string &Result) { 60590b57cec5SDimitry Andric Result += "__OFFSETOFIVAR__(struct "; 60600b57cec5SDimitry Andric Result += ivar->getContainingInterface()->getNameAsString(); 60610b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 60620b57cec5SDimitry Andric Result += "_IMPL"; 60630b57cec5SDimitry Andric Result += ", "; 60640b57cec5SDimitry Andric if (ivar->isBitField()) 60650b57cec5SDimitry Andric ObjCIvarBitfieldGroupDecl(ivar, Result); 60660b57cec5SDimitry Andric else 60670b57cec5SDimitry Andric Result += ivar->getNameAsString(); 60680b57cec5SDimitry Andric Result += ")"; 60690b57cec5SDimitry Andric } 60700b57cec5SDimitry Andric 60710b57cec5SDimitry Andric /// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI. 60720b57cec5SDimitry Andric /// struct _prop_t { 60730b57cec5SDimitry Andric /// const char *name; 60740b57cec5SDimitry Andric /// char *attributes; 60750b57cec5SDimitry Andric /// } 60760b57cec5SDimitry Andric 60770b57cec5SDimitry Andric /// struct _prop_list_t { 60780b57cec5SDimitry Andric /// uint32_t entsize; // sizeof(struct _prop_t) 60790b57cec5SDimitry Andric /// uint32_t count_of_properties; 60800b57cec5SDimitry Andric /// struct _prop_t prop_list[count_of_properties]; 60810b57cec5SDimitry Andric /// } 60820b57cec5SDimitry Andric 60830b57cec5SDimitry Andric /// struct _protocol_t; 60840b57cec5SDimitry Andric 60850b57cec5SDimitry Andric /// struct _protocol_list_t { 60860b57cec5SDimitry Andric /// long protocol_count; // Note, this is 32/64 bit 60870b57cec5SDimitry Andric /// struct _protocol_t * protocol_list[protocol_count]; 60880b57cec5SDimitry Andric /// } 60890b57cec5SDimitry Andric 60900b57cec5SDimitry Andric /// struct _objc_method { 60910b57cec5SDimitry Andric /// SEL _cmd; 60920b57cec5SDimitry Andric /// const char *method_type; 60930b57cec5SDimitry Andric /// char *_imp; 60940b57cec5SDimitry Andric /// } 60950b57cec5SDimitry Andric 60960b57cec5SDimitry Andric /// struct _method_list_t { 60970b57cec5SDimitry Andric /// uint32_t entsize; // sizeof(struct _objc_method) 60980b57cec5SDimitry Andric /// uint32_t method_count; 60990b57cec5SDimitry Andric /// struct _objc_method method_list[method_count]; 61000b57cec5SDimitry Andric /// } 61010b57cec5SDimitry Andric 61020b57cec5SDimitry Andric /// struct _protocol_t { 61030b57cec5SDimitry Andric /// id isa; // NULL 61040b57cec5SDimitry Andric /// const char *protocol_name; 61050b57cec5SDimitry Andric /// const struct _protocol_list_t * protocol_list; // super protocols 61060b57cec5SDimitry Andric /// const struct method_list_t *instance_methods; 61070b57cec5SDimitry Andric /// const struct method_list_t *class_methods; 61080b57cec5SDimitry Andric /// const struct method_list_t *optionalInstanceMethods; 61090b57cec5SDimitry Andric /// const struct method_list_t *optionalClassMethods; 61100b57cec5SDimitry Andric /// const struct _prop_list_t * properties; 61110b57cec5SDimitry Andric /// const uint32_t size; // sizeof(struct _protocol_t) 61120b57cec5SDimitry Andric /// const uint32_t flags; // = 0 61130b57cec5SDimitry Andric /// const char ** extendedMethodTypes; 61140b57cec5SDimitry Andric /// } 61150b57cec5SDimitry Andric 61160b57cec5SDimitry Andric /// struct _ivar_t { 61170b57cec5SDimitry Andric /// unsigned long int *offset; // pointer to ivar offset location 61180b57cec5SDimitry Andric /// const char *name; 61190b57cec5SDimitry Andric /// const char *type; 61200b57cec5SDimitry Andric /// uint32_t alignment; 61210b57cec5SDimitry Andric /// uint32_t size; 61220b57cec5SDimitry Andric /// } 61230b57cec5SDimitry Andric 61240b57cec5SDimitry Andric /// struct _ivar_list_t { 61250b57cec5SDimitry Andric /// uint32 entsize; // sizeof(struct _ivar_t) 61260b57cec5SDimitry Andric /// uint32 count; 61270b57cec5SDimitry Andric /// struct _ivar_t list[count]; 61280b57cec5SDimitry Andric /// } 61290b57cec5SDimitry Andric 61300b57cec5SDimitry Andric /// struct _class_ro_t { 61310b57cec5SDimitry Andric /// uint32_t flags; 61320b57cec5SDimitry Andric /// uint32_t instanceStart; 61330b57cec5SDimitry Andric /// uint32_t instanceSize; 61340b57cec5SDimitry Andric /// uint32_t reserved; // only when building for 64bit targets 61350b57cec5SDimitry Andric /// const uint8_t *ivarLayout; 61360b57cec5SDimitry Andric /// const char *name; 61370b57cec5SDimitry Andric /// const struct _method_list_t *baseMethods; 61380b57cec5SDimitry Andric /// const struct _protocol_list_t *baseProtocols; 61390b57cec5SDimitry Andric /// const struct _ivar_list_t *ivars; 61400b57cec5SDimitry Andric /// const uint8_t *weakIvarLayout; 61410b57cec5SDimitry Andric /// const struct _prop_list_t *properties; 61420b57cec5SDimitry Andric /// } 61430b57cec5SDimitry Andric 61440b57cec5SDimitry Andric /// struct _class_t { 61450b57cec5SDimitry Andric /// struct _class_t *isa; 61460b57cec5SDimitry Andric /// struct _class_t *superclass; 61470b57cec5SDimitry Andric /// void *cache; 61480b57cec5SDimitry Andric /// IMP *vtable; 61490b57cec5SDimitry Andric /// struct _class_ro_t *ro; 61500b57cec5SDimitry Andric /// } 61510b57cec5SDimitry Andric 61520b57cec5SDimitry Andric /// struct _category_t { 61530b57cec5SDimitry Andric /// const char *name; 61540b57cec5SDimitry Andric /// struct _class_t *cls; 61550b57cec5SDimitry Andric /// const struct _method_list_t *instance_methods; 61560b57cec5SDimitry Andric /// const struct _method_list_t *class_methods; 61570b57cec5SDimitry Andric /// const struct _protocol_list_t *protocols; 61580b57cec5SDimitry Andric /// const struct _prop_list_t *properties; 61590b57cec5SDimitry Andric /// } 61600b57cec5SDimitry Andric 61610b57cec5SDimitry Andric /// MessageRefTy - LLVM for: 61620b57cec5SDimitry Andric /// struct _message_ref_t { 61630b57cec5SDimitry Andric /// IMP messenger; 61640b57cec5SDimitry Andric /// SEL name; 61650b57cec5SDimitry Andric /// }; 61660b57cec5SDimitry Andric 61670b57cec5SDimitry Andric /// SuperMessageRefTy - LLVM for: 61680b57cec5SDimitry Andric /// struct _super_message_ref_t { 61690b57cec5SDimitry Andric /// SUPER_IMP messenger; 61700b57cec5SDimitry Andric /// SEL name; 61710b57cec5SDimitry Andric /// }; 61720b57cec5SDimitry Andric 61730b57cec5SDimitry Andric static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) { 61740b57cec5SDimitry Andric static bool meta_data_declared = false; 61750b57cec5SDimitry Andric if (meta_data_declared) 61760b57cec5SDimitry Andric return; 61770b57cec5SDimitry Andric 61780b57cec5SDimitry Andric Result += "\nstruct _prop_t {\n"; 61790b57cec5SDimitry Andric Result += "\tconst char *name;\n"; 61800b57cec5SDimitry Andric Result += "\tconst char *attributes;\n"; 61810b57cec5SDimitry Andric Result += "};\n"; 61820b57cec5SDimitry Andric 61830b57cec5SDimitry Andric Result += "\nstruct _protocol_t;\n"; 61840b57cec5SDimitry Andric 61850b57cec5SDimitry Andric Result += "\nstruct _objc_method {\n"; 61860b57cec5SDimitry Andric Result += "\tstruct objc_selector * _cmd;\n"; 61870b57cec5SDimitry Andric Result += "\tconst char *method_type;\n"; 61880b57cec5SDimitry Andric Result += "\tvoid *_imp;\n"; 61890b57cec5SDimitry Andric Result += "};\n"; 61900b57cec5SDimitry Andric 61910b57cec5SDimitry Andric Result += "\nstruct _protocol_t {\n"; 61920b57cec5SDimitry Andric Result += "\tvoid * isa; // NULL\n"; 61930b57cec5SDimitry Andric Result += "\tconst char *protocol_name;\n"; 61940b57cec5SDimitry Andric Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n"; 61950b57cec5SDimitry Andric Result += "\tconst struct method_list_t *instance_methods;\n"; 61960b57cec5SDimitry Andric Result += "\tconst struct method_list_t *class_methods;\n"; 61970b57cec5SDimitry Andric Result += "\tconst struct method_list_t *optionalInstanceMethods;\n"; 61980b57cec5SDimitry Andric Result += "\tconst struct method_list_t *optionalClassMethods;\n"; 61990b57cec5SDimitry Andric Result += "\tconst struct _prop_list_t * properties;\n"; 62000b57cec5SDimitry Andric Result += "\tconst unsigned int size; // sizeof(struct _protocol_t)\n"; 62010b57cec5SDimitry Andric Result += "\tconst unsigned int flags; // = 0\n"; 62020b57cec5SDimitry Andric Result += "\tconst char ** extendedMethodTypes;\n"; 62030b57cec5SDimitry Andric Result += "};\n"; 62040b57cec5SDimitry Andric 62050b57cec5SDimitry Andric Result += "\nstruct _ivar_t {\n"; 62060b57cec5SDimitry Andric Result += "\tunsigned long int *offset; // pointer to ivar offset location\n"; 62070b57cec5SDimitry Andric Result += "\tconst char *name;\n"; 62080b57cec5SDimitry Andric Result += "\tconst char *type;\n"; 62090b57cec5SDimitry Andric Result += "\tunsigned int alignment;\n"; 62100b57cec5SDimitry Andric Result += "\tunsigned int size;\n"; 62110b57cec5SDimitry Andric Result += "};\n"; 62120b57cec5SDimitry Andric 62130b57cec5SDimitry Andric Result += "\nstruct _class_ro_t {\n"; 62140b57cec5SDimitry Andric Result += "\tunsigned int flags;\n"; 62150b57cec5SDimitry Andric Result += "\tunsigned int instanceStart;\n"; 62160b57cec5SDimitry Andric Result += "\tunsigned int instanceSize;\n"; 62170b57cec5SDimitry Andric const llvm::Triple &Triple(Context->getTargetInfo().getTriple()); 62180b57cec5SDimitry Andric if (Triple.getArch() == llvm::Triple::x86_64) 62190b57cec5SDimitry Andric Result += "\tunsigned int reserved;\n"; 62200b57cec5SDimitry Andric Result += "\tconst unsigned char *ivarLayout;\n"; 62210b57cec5SDimitry Andric Result += "\tconst char *name;\n"; 62220b57cec5SDimitry Andric Result += "\tconst struct _method_list_t *baseMethods;\n"; 62230b57cec5SDimitry Andric Result += "\tconst struct _objc_protocol_list *baseProtocols;\n"; 62240b57cec5SDimitry Andric Result += "\tconst struct _ivar_list_t *ivars;\n"; 62250b57cec5SDimitry Andric Result += "\tconst unsigned char *weakIvarLayout;\n"; 62260b57cec5SDimitry Andric Result += "\tconst struct _prop_list_t *properties;\n"; 62270b57cec5SDimitry Andric Result += "};\n"; 62280b57cec5SDimitry Andric 62290b57cec5SDimitry Andric Result += "\nstruct _class_t {\n"; 62300b57cec5SDimitry Andric Result += "\tstruct _class_t *isa;\n"; 62310b57cec5SDimitry Andric Result += "\tstruct _class_t *superclass;\n"; 62320b57cec5SDimitry Andric Result += "\tvoid *cache;\n"; 62330b57cec5SDimitry Andric Result += "\tvoid *vtable;\n"; 62340b57cec5SDimitry Andric Result += "\tstruct _class_ro_t *ro;\n"; 62350b57cec5SDimitry Andric Result += "};\n"; 62360b57cec5SDimitry Andric 62370b57cec5SDimitry Andric Result += "\nstruct _category_t {\n"; 62380b57cec5SDimitry Andric Result += "\tconst char *name;\n"; 62390b57cec5SDimitry Andric Result += "\tstruct _class_t *cls;\n"; 62400b57cec5SDimitry Andric Result += "\tconst struct _method_list_t *instance_methods;\n"; 62410b57cec5SDimitry Andric Result += "\tconst struct _method_list_t *class_methods;\n"; 62420b57cec5SDimitry Andric Result += "\tconst struct _protocol_list_t *protocols;\n"; 62430b57cec5SDimitry Andric Result += "\tconst struct _prop_list_t *properties;\n"; 62440b57cec5SDimitry Andric Result += "};\n"; 62450b57cec5SDimitry Andric 62460b57cec5SDimitry Andric Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n"; 62470b57cec5SDimitry Andric Result += "#pragma warning(disable:4273)\n"; 62480b57cec5SDimitry Andric meta_data_declared = true; 62490b57cec5SDimitry Andric } 62500b57cec5SDimitry Andric 62510b57cec5SDimitry Andric static void Write_protocol_list_t_TypeDecl(std::string &Result, 62520b57cec5SDimitry Andric long super_protocol_count) { 62530b57cec5SDimitry Andric Result += "struct /*_protocol_list_t*/"; Result += " {\n"; 62540b57cec5SDimitry Andric Result += "\tlong protocol_count; // Note, this is 32/64 bit\n"; 62550b57cec5SDimitry Andric Result += "\tstruct _protocol_t *super_protocols["; 62560b57cec5SDimitry Andric Result += utostr(super_protocol_count); Result += "];\n"; 62570b57cec5SDimitry Andric Result += "}"; 62580b57cec5SDimitry Andric } 62590b57cec5SDimitry Andric 62600b57cec5SDimitry Andric static void Write_method_list_t_TypeDecl(std::string &Result, 62610b57cec5SDimitry Andric unsigned int method_count) { 62620b57cec5SDimitry Andric Result += "struct /*_method_list_t*/"; Result += " {\n"; 62630b57cec5SDimitry Andric Result += "\tunsigned int entsize; // sizeof(struct _objc_method)\n"; 62640b57cec5SDimitry Andric Result += "\tunsigned int method_count;\n"; 62650b57cec5SDimitry Andric Result += "\tstruct _objc_method method_list["; 62660b57cec5SDimitry Andric Result += utostr(method_count); Result += "];\n"; 62670b57cec5SDimitry Andric Result += "}"; 62680b57cec5SDimitry Andric } 62690b57cec5SDimitry Andric 62700b57cec5SDimitry Andric static void Write__prop_list_t_TypeDecl(std::string &Result, 62710b57cec5SDimitry Andric unsigned int property_count) { 62720b57cec5SDimitry Andric Result += "struct /*_prop_list_t*/"; Result += " {\n"; 62730b57cec5SDimitry Andric Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n"; 62740b57cec5SDimitry Andric Result += "\tunsigned int count_of_properties;\n"; 62750b57cec5SDimitry Andric Result += "\tstruct _prop_t prop_list["; 62760b57cec5SDimitry Andric Result += utostr(property_count); Result += "];\n"; 62770b57cec5SDimitry Andric Result += "}"; 62780b57cec5SDimitry Andric } 62790b57cec5SDimitry Andric 62800b57cec5SDimitry Andric static void Write__ivar_list_t_TypeDecl(std::string &Result, 62810b57cec5SDimitry Andric unsigned int ivar_count) { 62820b57cec5SDimitry Andric Result += "struct /*_ivar_list_t*/"; Result += " {\n"; 62830b57cec5SDimitry Andric Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n"; 62840b57cec5SDimitry Andric Result += "\tunsigned int count;\n"; 62850b57cec5SDimitry Andric Result += "\tstruct _ivar_t ivar_list["; 62860b57cec5SDimitry Andric Result += utostr(ivar_count); Result += "];\n"; 62870b57cec5SDimitry Andric Result += "}"; 62880b57cec5SDimitry Andric } 62890b57cec5SDimitry Andric 62900b57cec5SDimitry Andric static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result, 62910b57cec5SDimitry Andric ArrayRef<ObjCProtocolDecl *> SuperProtocols, 62920b57cec5SDimitry Andric StringRef VarName, 62930b57cec5SDimitry Andric StringRef ProtocolName) { 62940b57cec5SDimitry Andric if (SuperProtocols.size() > 0) { 62950b57cec5SDimitry Andric Result += "\nstatic "; 62960b57cec5SDimitry Andric Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size()); 62970b57cec5SDimitry Andric Result += " "; Result += VarName; 62980b57cec5SDimitry Andric Result += ProtocolName; 62990b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 63000b57cec5SDimitry Andric Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n"; 63010b57cec5SDimitry Andric for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) { 63020b57cec5SDimitry Andric ObjCProtocolDecl *SuperPD = SuperProtocols[i]; 63030b57cec5SDimitry Andric Result += "\t&"; Result += "_OBJC_PROTOCOL_"; 63040b57cec5SDimitry Andric Result += SuperPD->getNameAsString(); 63050b57cec5SDimitry Andric if (i == e-1) 63060b57cec5SDimitry Andric Result += "\n};\n"; 63070b57cec5SDimitry Andric else 63080b57cec5SDimitry Andric Result += ",\n"; 63090b57cec5SDimitry Andric } 63100b57cec5SDimitry Andric } 63110b57cec5SDimitry Andric } 63120b57cec5SDimitry Andric 63130b57cec5SDimitry Andric static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj, 63140b57cec5SDimitry Andric ASTContext *Context, std::string &Result, 63150b57cec5SDimitry Andric ArrayRef<ObjCMethodDecl *> Methods, 63160b57cec5SDimitry Andric StringRef VarName, 63170b57cec5SDimitry Andric StringRef TopLevelDeclName, 63180b57cec5SDimitry Andric bool MethodImpl) { 63190b57cec5SDimitry Andric if (Methods.size() > 0) { 63200b57cec5SDimitry Andric Result += "\nstatic "; 63210b57cec5SDimitry Andric Write_method_list_t_TypeDecl(Result, Methods.size()); 63220b57cec5SDimitry Andric Result += " "; Result += VarName; 63230b57cec5SDimitry Andric Result += TopLevelDeclName; 63240b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 63250b57cec5SDimitry Andric Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n"; 63260b57cec5SDimitry Andric Result += "\t"; Result += utostr(Methods.size()); Result += ",\n"; 63270b57cec5SDimitry Andric for (unsigned i = 0, e = Methods.size(); i < e; i++) { 63280b57cec5SDimitry Andric ObjCMethodDecl *MD = Methods[i]; 63290b57cec5SDimitry Andric if (i == 0) 63300b57cec5SDimitry Andric Result += "\t{{(struct objc_selector *)\""; 63310b57cec5SDimitry Andric else 63320b57cec5SDimitry Andric Result += "\t{(struct objc_selector *)\""; 63330b57cec5SDimitry Andric Result += (MD)->getSelector().getAsString(); Result += "\""; 63340b57cec5SDimitry Andric Result += ", "; 63350b57cec5SDimitry Andric std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(MD); 63360b57cec5SDimitry Andric Result += "\""; Result += MethodTypeString; Result += "\""; 63370b57cec5SDimitry Andric Result += ", "; 63380b57cec5SDimitry Andric if (!MethodImpl) 63390b57cec5SDimitry Andric Result += "0"; 63400b57cec5SDimitry Andric else { 63410b57cec5SDimitry Andric Result += "(void *)"; 63420b57cec5SDimitry Andric Result += RewriteObj.MethodInternalNames[MD]; 63430b57cec5SDimitry Andric } 63440b57cec5SDimitry Andric if (i == e-1) 63450b57cec5SDimitry Andric Result += "}}\n"; 63460b57cec5SDimitry Andric else 63470b57cec5SDimitry Andric Result += "},\n"; 63480b57cec5SDimitry Andric } 63490b57cec5SDimitry Andric Result += "};\n"; 63500b57cec5SDimitry Andric } 63510b57cec5SDimitry Andric } 63520b57cec5SDimitry Andric 63530b57cec5SDimitry Andric static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj, 63540b57cec5SDimitry Andric ASTContext *Context, std::string &Result, 63550b57cec5SDimitry Andric ArrayRef<ObjCPropertyDecl *> Properties, 63560b57cec5SDimitry Andric const Decl *Container, 63570b57cec5SDimitry Andric StringRef VarName, 63580b57cec5SDimitry Andric StringRef ProtocolName) { 63590b57cec5SDimitry Andric if (Properties.size() > 0) { 63600b57cec5SDimitry Andric Result += "\nstatic "; 63610b57cec5SDimitry Andric Write__prop_list_t_TypeDecl(Result, Properties.size()); 63620b57cec5SDimitry Andric Result += " "; Result += VarName; 63630b57cec5SDimitry Andric Result += ProtocolName; 63640b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 63650b57cec5SDimitry Andric Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n"; 63660b57cec5SDimitry Andric Result += "\t"; Result += utostr(Properties.size()); Result += ",\n"; 63670b57cec5SDimitry Andric for (unsigned i = 0, e = Properties.size(); i < e; i++) { 63680b57cec5SDimitry Andric ObjCPropertyDecl *PropDecl = Properties[i]; 63690b57cec5SDimitry Andric if (i == 0) 63700b57cec5SDimitry Andric Result += "\t{{\""; 63710b57cec5SDimitry Andric else 63720b57cec5SDimitry Andric Result += "\t{\""; 63730b57cec5SDimitry Andric Result += PropDecl->getName(); Result += "\","; 63740b57cec5SDimitry Andric std::string PropertyTypeString = 63750b57cec5SDimitry Andric Context->getObjCEncodingForPropertyDecl(PropDecl, Container); 63760b57cec5SDimitry Andric std::string QuotePropertyTypeString; 63770b57cec5SDimitry Andric RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString); 63780b57cec5SDimitry Andric Result += "\""; Result += QuotePropertyTypeString; Result += "\""; 63790b57cec5SDimitry Andric if (i == e-1) 63800b57cec5SDimitry Andric Result += "}}\n"; 63810b57cec5SDimitry Andric else 63820b57cec5SDimitry Andric Result += "},\n"; 63830b57cec5SDimitry Andric } 63840b57cec5SDimitry Andric Result += "};\n"; 63850b57cec5SDimitry Andric } 63860b57cec5SDimitry Andric } 63870b57cec5SDimitry Andric 63880b57cec5SDimitry Andric // Metadata flags 63890b57cec5SDimitry Andric enum MetaDataDlags { 63900b57cec5SDimitry Andric CLS = 0x0, 63910b57cec5SDimitry Andric CLS_META = 0x1, 63920b57cec5SDimitry Andric CLS_ROOT = 0x2, 63930b57cec5SDimitry Andric OBJC2_CLS_HIDDEN = 0x10, 63940b57cec5SDimitry Andric CLS_EXCEPTION = 0x20, 63950b57cec5SDimitry Andric 63960b57cec5SDimitry Andric /// (Obsolete) ARC-specific: this class has a .release_ivars method 63970b57cec5SDimitry Andric CLS_HAS_IVAR_RELEASER = 0x40, 63980b57cec5SDimitry Andric /// class was compiled with -fobjc-arr 63990b57cec5SDimitry Andric CLS_COMPILED_BY_ARC = 0x80 // (1<<7) 64000b57cec5SDimitry Andric }; 64010b57cec5SDimitry Andric 64020b57cec5SDimitry Andric static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result, 64030b57cec5SDimitry Andric unsigned int flags, 64040b57cec5SDimitry Andric const std::string &InstanceStart, 64050b57cec5SDimitry Andric const std::string &InstanceSize, 64060b57cec5SDimitry Andric ArrayRef<ObjCMethodDecl *>baseMethods, 64070b57cec5SDimitry Andric ArrayRef<ObjCProtocolDecl *>baseProtocols, 64080b57cec5SDimitry Andric ArrayRef<ObjCIvarDecl *>ivars, 64090b57cec5SDimitry Andric ArrayRef<ObjCPropertyDecl *>Properties, 64100b57cec5SDimitry Andric StringRef VarName, 64110b57cec5SDimitry Andric StringRef ClassName) { 64120b57cec5SDimitry Andric Result += "\nstatic struct _class_ro_t "; 64130b57cec5SDimitry Andric Result += VarName; Result += ClassName; 64140b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 64150b57cec5SDimitry Andric Result += "\t"; 64160b57cec5SDimitry Andric Result += llvm::utostr(flags); Result += ", "; 64170b57cec5SDimitry Andric Result += InstanceStart; Result += ", "; 64180b57cec5SDimitry Andric Result += InstanceSize; Result += ", \n"; 64190b57cec5SDimitry Andric Result += "\t"; 64200b57cec5SDimitry Andric const llvm::Triple &Triple(Context->getTargetInfo().getTriple()); 64210b57cec5SDimitry Andric if (Triple.getArch() == llvm::Triple::x86_64) 64220b57cec5SDimitry Andric // uint32_t const reserved; // only when building for 64bit targets 64230b57cec5SDimitry Andric Result += "(unsigned int)0, \n\t"; 64240b57cec5SDimitry Andric // const uint8_t * const ivarLayout; 64250b57cec5SDimitry Andric Result += "0, \n\t"; 64260b57cec5SDimitry Andric Result += "\""; Result += ClassName; Result += "\",\n\t"; 64270b57cec5SDimitry Andric bool metaclass = ((flags & CLS_META) != 0); 64280b57cec5SDimitry Andric if (baseMethods.size() > 0) { 64290b57cec5SDimitry Andric Result += "(const struct _method_list_t *)&"; 64300b57cec5SDimitry Andric if (metaclass) 64310b57cec5SDimitry Andric Result += "_OBJC_$_CLASS_METHODS_"; 64320b57cec5SDimitry Andric else 64330b57cec5SDimitry Andric Result += "_OBJC_$_INSTANCE_METHODS_"; 64340b57cec5SDimitry Andric Result += ClassName; 64350b57cec5SDimitry Andric Result += ",\n\t"; 64360b57cec5SDimitry Andric } 64370b57cec5SDimitry Andric else 64380b57cec5SDimitry Andric Result += "0, \n\t"; 64390b57cec5SDimitry Andric 64400b57cec5SDimitry Andric if (!metaclass && baseProtocols.size() > 0) { 64410b57cec5SDimitry Andric Result += "(const struct _objc_protocol_list *)&"; 64420b57cec5SDimitry Andric Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName; 64430b57cec5SDimitry Andric Result += ",\n\t"; 64440b57cec5SDimitry Andric } 64450b57cec5SDimitry Andric else 64460b57cec5SDimitry Andric Result += "0, \n\t"; 64470b57cec5SDimitry Andric 64480b57cec5SDimitry Andric if (!metaclass && ivars.size() > 0) { 64490b57cec5SDimitry Andric Result += "(const struct _ivar_list_t *)&"; 64500b57cec5SDimitry Andric Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName; 64510b57cec5SDimitry Andric Result += ",\n\t"; 64520b57cec5SDimitry Andric } 64530b57cec5SDimitry Andric else 64540b57cec5SDimitry Andric Result += "0, \n\t"; 64550b57cec5SDimitry Andric 64560b57cec5SDimitry Andric // weakIvarLayout 64570b57cec5SDimitry Andric Result += "0, \n\t"; 64580b57cec5SDimitry Andric if (!metaclass && Properties.size() > 0) { 64590b57cec5SDimitry Andric Result += "(const struct _prop_list_t *)&"; 64600b57cec5SDimitry Andric Result += "_OBJC_$_PROP_LIST_"; Result += ClassName; 64610b57cec5SDimitry Andric Result += ",\n"; 64620b57cec5SDimitry Andric } 64630b57cec5SDimitry Andric else 64640b57cec5SDimitry Andric Result += "0, \n"; 64650b57cec5SDimitry Andric 64660b57cec5SDimitry Andric Result += "};\n"; 64670b57cec5SDimitry Andric } 64680b57cec5SDimitry Andric 64690b57cec5SDimitry Andric static void Write_class_t(ASTContext *Context, std::string &Result, 64700b57cec5SDimitry Andric StringRef VarName, 64710b57cec5SDimitry Andric const ObjCInterfaceDecl *CDecl, bool metaclass) { 64720b57cec5SDimitry Andric bool rootClass = (!CDecl->getSuperClass()); 64730b57cec5SDimitry Andric const ObjCInterfaceDecl *RootClass = CDecl; 64740b57cec5SDimitry Andric 64750b57cec5SDimitry Andric if (!rootClass) { 64760b57cec5SDimitry Andric // Find the Root class 64770b57cec5SDimitry Andric RootClass = CDecl->getSuperClass(); 64780b57cec5SDimitry Andric while (RootClass->getSuperClass()) { 64790b57cec5SDimitry Andric RootClass = RootClass->getSuperClass(); 64800b57cec5SDimitry Andric } 64810b57cec5SDimitry Andric } 64820b57cec5SDimitry Andric 64830b57cec5SDimitry Andric if (metaclass && rootClass) { 64840b57cec5SDimitry Andric // Need to handle a case of use of forward declaration. 64850b57cec5SDimitry Andric Result += "\n"; 64860b57cec5SDimitry Andric Result += "extern \"C\" "; 64870b57cec5SDimitry Andric if (CDecl->getImplementation()) 64880b57cec5SDimitry Andric Result += "__declspec(dllexport) "; 64890b57cec5SDimitry Andric else 64900b57cec5SDimitry Andric Result += "__declspec(dllimport) "; 64910b57cec5SDimitry Andric 64920b57cec5SDimitry Andric Result += "struct _class_t OBJC_CLASS_$_"; 64930b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 64940b57cec5SDimitry Andric Result += ";\n"; 64950b57cec5SDimitry Andric } 64960b57cec5SDimitry Andric // Also, for possibility of 'super' metadata class not having been defined yet. 64970b57cec5SDimitry Andric if (!rootClass) { 64980b57cec5SDimitry Andric ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); 64990b57cec5SDimitry Andric Result += "\n"; 65000b57cec5SDimitry Andric Result += "extern \"C\" "; 65010b57cec5SDimitry Andric if (SuperClass->getImplementation()) 65020b57cec5SDimitry Andric Result += "__declspec(dllexport) "; 65030b57cec5SDimitry Andric else 65040b57cec5SDimitry Andric Result += "__declspec(dllimport) "; 65050b57cec5SDimitry Andric 65060b57cec5SDimitry Andric Result += "struct _class_t "; 65070b57cec5SDimitry Andric Result += VarName; 65080b57cec5SDimitry Andric Result += SuperClass->getNameAsString(); 65090b57cec5SDimitry Andric Result += ";\n"; 65100b57cec5SDimitry Andric 65110b57cec5SDimitry Andric if (metaclass && RootClass != SuperClass) { 65120b57cec5SDimitry Andric Result += "extern \"C\" "; 65130b57cec5SDimitry Andric if (RootClass->getImplementation()) 65140b57cec5SDimitry Andric Result += "__declspec(dllexport) "; 65150b57cec5SDimitry Andric else 65160b57cec5SDimitry Andric Result += "__declspec(dllimport) "; 65170b57cec5SDimitry Andric 65180b57cec5SDimitry Andric Result += "struct _class_t "; 65190b57cec5SDimitry Andric Result += VarName; 65200b57cec5SDimitry Andric Result += RootClass->getNameAsString(); 65210b57cec5SDimitry Andric Result += ";\n"; 65220b57cec5SDimitry Andric } 65230b57cec5SDimitry Andric } 65240b57cec5SDimitry Andric 65250b57cec5SDimitry Andric Result += "\nextern \"C\" __declspec(dllexport) struct _class_t "; 65260b57cec5SDimitry Andric Result += VarName; Result += CDecl->getNameAsString(); 65270b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n"; 65280b57cec5SDimitry Andric Result += "\t"; 65290b57cec5SDimitry Andric if (metaclass) { 65300b57cec5SDimitry Andric if (!rootClass) { 65310b57cec5SDimitry Andric Result += "0, // &"; Result += VarName; 65320b57cec5SDimitry Andric Result += RootClass->getNameAsString(); 65330b57cec5SDimitry Andric Result += ",\n\t"; 65340b57cec5SDimitry Andric Result += "0, // &"; Result += VarName; 65350b57cec5SDimitry Andric Result += CDecl->getSuperClass()->getNameAsString(); 65360b57cec5SDimitry Andric Result += ",\n\t"; 65370b57cec5SDimitry Andric } 65380b57cec5SDimitry Andric else { 65390b57cec5SDimitry Andric Result += "0, // &"; Result += VarName; 65400b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 65410b57cec5SDimitry Andric Result += ",\n\t"; 65420b57cec5SDimitry Andric Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 65430b57cec5SDimitry Andric Result += ",\n\t"; 65440b57cec5SDimitry Andric } 65450b57cec5SDimitry Andric } 65460b57cec5SDimitry Andric else { 65470b57cec5SDimitry Andric Result += "0, // &OBJC_METACLASS_$_"; 65480b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 65490b57cec5SDimitry Andric Result += ",\n\t"; 65500b57cec5SDimitry Andric if (!rootClass) { 65510b57cec5SDimitry Andric Result += "0, // &"; Result += VarName; 65520b57cec5SDimitry Andric Result += CDecl->getSuperClass()->getNameAsString(); 65530b57cec5SDimitry Andric Result += ",\n\t"; 65540b57cec5SDimitry Andric } 65550b57cec5SDimitry Andric else 65560b57cec5SDimitry Andric Result += "0,\n\t"; 65570b57cec5SDimitry Andric } 65580b57cec5SDimitry Andric Result += "0, // (void *)&_objc_empty_cache,\n\t"; 65590b57cec5SDimitry Andric Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t"; 65600b57cec5SDimitry Andric if (metaclass) 65610b57cec5SDimitry Andric Result += "&_OBJC_METACLASS_RO_$_"; 65620b57cec5SDimitry Andric else 65630b57cec5SDimitry Andric Result += "&_OBJC_CLASS_RO_$_"; 65640b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 65650b57cec5SDimitry Andric Result += ",\n};\n"; 65660b57cec5SDimitry Andric 65670b57cec5SDimitry Andric // Add static function to initialize some of the meta-data fields. 65680b57cec5SDimitry Andric // avoid doing it twice. 65690b57cec5SDimitry Andric if (metaclass) 65700b57cec5SDimitry Andric return; 65710b57cec5SDimitry Andric 65720b57cec5SDimitry Andric const ObjCInterfaceDecl *SuperClass = 65730b57cec5SDimitry Andric rootClass ? CDecl : CDecl->getSuperClass(); 65740b57cec5SDimitry Andric 65750b57cec5SDimitry Andric Result += "static void OBJC_CLASS_SETUP_$_"; 65760b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 65770b57cec5SDimitry Andric Result += "(void ) {\n"; 65780b57cec5SDimitry Andric Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 65790b57cec5SDimitry Andric Result += ".isa = "; Result += "&OBJC_METACLASS_$_"; 65800b57cec5SDimitry Andric Result += RootClass->getNameAsString(); Result += ";\n"; 65810b57cec5SDimitry Andric 65820b57cec5SDimitry Andric Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 65830b57cec5SDimitry Andric Result += ".superclass = "; 65840b57cec5SDimitry Andric if (rootClass) 65850b57cec5SDimitry Andric Result += "&OBJC_CLASS_$_"; 65860b57cec5SDimitry Andric else 65870b57cec5SDimitry Andric Result += "&OBJC_METACLASS_$_"; 65880b57cec5SDimitry Andric 65890b57cec5SDimitry Andric Result += SuperClass->getNameAsString(); Result += ";\n"; 65900b57cec5SDimitry Andric 65910b57cec5SDimitry Andric Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 65920b57cec5SDimitry Andric Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n"; 65930b57cec5SDimitry Andric 65940b57cec5SDimitry Andric Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 65950b57cec5SDimitry Andric Result += ".isa = "; Result += "&OBJC_METACLASS_$_"; 65960b57cec5SDimitry Andric Result += CDecl->getNameAsString(); Result += ";\n"; 65970b57cec5SDimitry Andric 65980b57cec5SDimitry Andric if (!rootClass) { 65990b57cec5SDimitry Andric Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 66000b57cec5SDimitry Andric Result += ".superclass = "; Result += "&OBJC_CLASS_$_"; 66010b57cec5SDimitry Andric Result += SuperClass->getNameAsString(); Result += ";\n"; 66020b57cec5SDimitry Andric } 66030b57cec5SDimitry Andric 66040b57cec5SDimitry Andric Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 66050b57cec5SDimitry Andric Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n"; 66060b57cec5SDimitry Andric Result += "}\n"; 66070b57cec5SDimitry Andric } 66080b57cec5SDimitry Andric 66090b57cec5SDimitry Andric static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context, 66100b57cec5SDimitry Andric std::string &Result, 66110b57cec5SDimitry Andric ObjCCategoryDecl *CatDecl, 66120b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDecl, 66130b57cec5SDimitry Andric ArrayRef<ObjCMethodDecl *> InstanceMethods, 66140b57cec5SDimitry Andric ArrayRef<ObjCMethodDecl *> ClassMethods, 66150b57cec5SDimitry Andric ArrayRef<ObjCProtocolDecl *> RefedProtocols, 66160b57cec5SDimitry Andric ArrayRef<ObjCPropertyDecl *> ClassProperties) { 66170b57cec5SDimitry Andric StringRef CatName = CatDecl->getName(); 66180b57cec5SDimitry Andric StringRef ClassName = ClassDecl->getName(); 66190b57cec5SDimitry Andric // must declare an extern class object in case this class is not implemented 66200b57cec5SDimitry Andric // in this TU. 66210b57cec5SDimitry Andric Result += "\n"; 66220b57cec5SDimitry Andric Result += "extern \"C\" "; 66230b57cec5SDimitry Andric if (ClassDecl->getImplementation()) 66240b57cec5SDimitry Andric Result += "__declspec(dllexport) "; 66250b57cec5SDimitry Andric else 66260b57cec5SDimitry Andric Result += "__declspec(dllimport) "; 66270b57cec5SDimitry Andric 66280b57cec5SDimitry Andric Result += "struct _class_t "; 66290b57cec5SDimitry Andric Result += "OBJC_CLASS_$_"; Result += ClassName; 66300b57cec5SDimitry Andric Result += ";\n"; 66310b57cec5SDimitry Andric 66320b57cec5SDimitry Andric Result += "\nstatic struct _category_t "; 66330b57cec5SDimitry Andric Result += "_OBJC_$_CATEGORY_"; 66340b57cec5SDimitry Andric Result += ClassName; Result += "_$_"; Result += CatName; 66350b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n"; 66360b57cec5SDimitry Andric Result += "{\n"; 66370b57cec5SDimitry Andric Result += "\t\""; Result += ClassName; Result += "\",\n"; 66380b57cec5SDimitry Andric Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName; 66390b57cec5SDimitry Andric Result += ",\n"; 66400b57cec5SDimitry Andric if (InstanceMethods.size() > 0) { 66410b57cec5SDimitry Andric Result += "\t(const struct _method_list_t *)&"; 66420b57cec5SDimitry Andric Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_"; 66430b57cec5SDimitry Andric Result += ClassName; Result += "_$_"; Result += CatName; 66440b57cec5SDimitry Andric Result += ",\n"; 66450b57cec5SDimitry Andric } 66460b57cec5SDimitry Andric else 66470b57cec5SDimitry Andric Result += "\t0,\n"; 66480b57cec5SDimitry Andric 66490b57cec5SDimitry Andric if (ClassMethods.size() > 0) { 66500b57cec5SDimitry Andric Result += "\t(const struct _method_list_t *)&"; 66510b57cec5SDimitry Andric Result += "_OBJC_$_CATEGORY_CLASS_METHODS_"; 66520b57cec5SDimitry Andric Result += ClassName; Result += "_$_"; Result += CatName; 66530b57cec5SDimitry Andric Result += ",\n"; 66540b57cec5SDimitry Andric } 66550b57cec5SDimitry Andric else 66560b57cec5SDimitry Andric Result += "\t0,\n"; 66570b57cec5SDimitry Andric 66580b57cec5SDimitry Andric if (RefedProtocols.size() > 0) { 66590b57cec5SDimitry Andric Result += "\t(const struct _protocol_list_t *)&"; 66600b57cec5SDimitry Andric Result += "_OBJC_CATEGORY_PROTOCOLS_$_"; 66610b57cec5SDimitry Andric Result += ClassName; Result += "_$_"; Result += CatName; 66620b57cec5SDimitry Andric Result += ",\n"; 66630b57cec5SDimitry Andric } 66640b57cec5SDimitry Andric else 66650b57cec5SDimitry Andric Result += "\t0,\n"; 66660b57cec5SDimitry Andric 66670b57cec5SDimitry Andric if (ClassProperties.size() > 0) { 66680b57cec5SDimitry Andric Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_"; 66690b57cec5SDimitry Andric Result += ClassName; Result += "_$_"; Result += CatName; 66700b57cec5SDimitry Andric Result += ",\n"; 66710b57cec5SDimitry Andric } 66720b57cec5SDimitry Andric else 66730b57cec5SDimitry Andric Result += "\t0,\n"; 66740b57cec5SDimitry Andric 66750b57cec5SDimitry Andric Result += "};\n"; 66760b57cec5SDimitry Andric 66770b57cec5SDimitry Andric // Add static function to initialize the class pointer in the category structure. 66780b57cec5SDimitry Andric Result += "static void OBJC_CATEGORY_SETUP_$_"; 66790b57cec5SDimitry Andric Result += ClassDecl->getNameAsString(); 66800b57cec5SDimitry Andric Result += "_$_"; 66810b57cec5SDimitry Andric Result += CatName; 66820b57cec5SDimitry Andric Result += "(void ) {\n"; 66830b57cec5SDimitry Andric Result += "\t_OBJC_$_CATEGORY_"; 66840b57cec5SDimitry Andric Result += ClassDecl->getNameAsString(); 66850b57cec5SDimitry Andric Result += "_$_"; 66860b57cec5SDimitry Andric Result += CatName; 66870b57cec5SDimitry Andric Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName; 66880b57cec5SDimitry Andric Result += ";\n}\n"; 66890b57cec5SDimitry Andric } 66900b57cec5SDimitry Andric 66910b57cec5SDimitry Andric static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj, 66920b57cec5SDimitry Andric ASTContext *Context, std::string &Result, 66930b57cec5SDimitry Andric ArrayRef<ObjCMethodDecl *> Methods, 66940b57cec5SDimitry Andric StringRef VarName, 66950b57cec5SDimitry Andric StringRef ProtocolName) { 66960b57cec5SDimitry Andric if (Methods.size() == 0) 66970b57cec5SDimitry Andric return; 66980b57cec5SDimitry Andric 66990b57cec5SDimitry Andric Result += "\nstatic const char *"; 67000b57cec5SDimitry Andric Result += VarName; Result += ProtocolName; 67010b57cec5SDimitry Andric Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n"; 67020b57cec5SDimitry Andric Result += "{\n"; 67030b57cec5SDimitry Andric for (unsigned i = 0, e = Methods.size(); i < e; i++) { 67040b57cec5SDimitry Andric ObjCMethodDecl *MD = Methods[i]; 67050b57cec5SDimitry Andric std::string MethodTypeString = 67060b57cec5SDimitry Andric Context->getObjCEncodingForMethodDecl(MD, true); 67070b57cec5SDimitry Andric std::string QuoteMethodTypeString; 67080b57cec5SDimitry Andric RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString); 67090b57cec5SDimitry Andric Result += "\t\""; Result += QuoteMethodTypeString; Result += "\""; 67100b57cec5SDimitry Andric if (i == e-1) 67110b57cec5SDimitry Andric Result += "\n};\n"; 67120b57cec5SDimitry Andric else { 67130b57cec5SDimitry Andric Result += ",\n"; 67140b57cec5SDimitry Andric } 67150b57cec5SDimitry Andric } 67160b57cec5SDimitry Andric } 67170b57cec5SDimitry Andric 67180b57cec5SDimitry Andric static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj, 67190b57cec5SDimitry Andric ASTContext *Context, 67200b57cec5SDimitry Andric std::string &Result, 67210b57cec5SDimitry Andric ArrayRef<ObjCIvarDecl *> Ivars, 67220b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl) { 6723bdd1243dSDimitry Andric // FIXME. visibility of offset symbols may have to be set; for Darwin 67240b57cec5SDimitry Andric // this is what happens: 67250b57cec5SDimitry Andric /** 67260b57cec5SDimitry Andric if (Ivar->getAccessControl() == ObjCIvarDecl::Private || 67270b57cec5SDimitry Andric Ivar->getAccessControl() == ObjCIvarDecl::Package || 67280b57cec5SDimitry Andric Class->getVisibility() == HiddenVisibility) 67290b57cec5SDimitry Andric Visibility should be: HiddenVisibility; 67300b57cec5SDimitry Andric else 67310b57cec5SDimitry Andric Visibility should be: DefaultVisibility; 67320b57cec5SDimitry Andric */ 67330b57cec5SDimitry Andric 67340b57cec5SDimitry Andric Result += "\n"; 67350b57cec5SDimitry Andric for (unsigned i =0, e = Ivars.size(); i < e; i++) { 67360b57cec5SDimitry Andric ObjCIvarDecl *IvarDecl = Ivars[i]; 67370b57cec5SDimitry Andric if (Context->getLangOpts().MicrosoftExt) 67380b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_ivar$B\")) "; 67390b57cec5SDimitry Andric 67400b57cec5SDimitry Andric if (!Context->getLangOpts().MicrosoftExt || 67410b57cec5SDimitry Andric IvarDecl->getAccessControl() == ObjCIvarDecl::Private || 67420b57cec5SDimitry Andric IvarDecl->getAccessControl() == ObjCIvarDecl::Package) 67430b57cec5SDimitry Andric Result += "extern \"C\" unsigned long int "; 67440b57cec5SDimitry Andric else 67450b57cec5SDimitry Andric Result += "extern \"C\" __declspec(dllexport) unsigned long int "; 67460b57cec5SDimitry Andric if (Ivars[i]->isBitField()) 67470b57cec5SDimitry Andric RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result); 67480b57cec5SDimitry Andric else 67490b57cec5SDimitry Andric WriteInternalIvarName(CDecl, IvarDecl, Result); 67500b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))"; 67510b57cec5SDimitry Andric Result += " = "; 67520b57cec5SDimitry Andric RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result); 67530b57cec5SDimitry Andric Result += ";\n"; 67540b57cec5SDimitry Andric if (Ivars[i]->isBitField()) { 67550b57cec5SDimitry Andric // skip over rest of the ivar bitfields. 67560b57cec5SDimitry Andric SKIP_BITFIELDS(i , e, Ivars); 67570b57cec5SDimitry Andric } 67580b57cec5SDimitry Andric } 67590b57cec5SDimitry Andric } 67600b57cec5SDimitry Andric 67610b57cec5SDimitry Andric static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj, 67620b57cec5SDimitry Andric ASTContext *Context, std::string &Result, 67630b57cec5SDimitry Andric ArrayRef<ObjCIvarDecl *> OriginalIvars, 67640b57cec5SDimitry Andric StringRef VarName, 67650b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl) { 67660b57cec5SDimitry Andric if (OriginalIvars.size() > 0) { 67670b57cec5SDimitry Andric Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl); 67680b57cec5SDimitry Andric SmallVector<ObjCIvarDecl *, 8> Ivars; 67690b57cec5SDimitry Andric // strip off all but the first ivar bitfield from each group of ivars. 67700b57cec5SDimitry Andric // Such ivars in the ivar list table will be replaced by their grouping struct 67710b57cec5SDimitry Andric // 'ivar'. 67720b57cec5SDimitry Andric for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) { 67730b57cec5SDimitry Andric if (OriginalIvars[i]->isBitField()) { 67740b57cec5SDimitry Andric Ivars.push_back(OriginalIvars[i]); 67750b57cec5SDimitry Andric // skip over rest of the ivar bitfields. 67760b57cec5SDimitry Andric SKIP_BITFIELDS(i , e, OriginalIvars); 67770b57cec5SDimitry Andric } 67780b57cec5SDimitry Andric else 67790b57cec5SDimitry Andric Ivars.push_back(OriginalIvars[i]); 67800b57cec5SDimitry Andric } 67810b57cec5SDimitry Andric 67820b57cec5SDimitry Andric Result += "\nstatic "; 67830b57cec5SDimitry Andric Write__ivar_list_t_TypeDecl(Result, Ivars.size()); 67840b57cec5SDimitry Andric Result += " "; Result += VarName; 67850b57cec5SDimitry Andric Result += CDecl->getNameAsString(); 67860b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 67870b57cec5SDimitry Andric Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n"; 67880b57cec5SDimitry Andric Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n"; 67890b57cec5SDimitry Andric for (unsigned i =0, e = Ivars.size(); i < e; i++) { 67900b57cec5SDimitry Andric ObjCIvarDecl *IvarDecl = Ivars[i]; 67910b57cec5SDimitry Andric if (i == 0) 67920b57cec5SDimitry Andric Result += "\t{{"; 67930b57cec5SDimitry Andric else 67940b57cec5SDimitry Andric Result += "\t {"; 67950b57cec5SDimitry Andric Result += "(unsigned long int *)&"; 67960b57cec5SDimitry Andric if (Ivars[i]->isBitField()) 67970b57cec5SDimitry Andric RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result); 67980b57cec5SDimitry Andric else 67990b57cec5SDimitry Andric WriteInternalIvarName(CDecl, IvarDecl, Result); 68000b57cec5SDimitry Andric Result += ", "; 68010b57cec5SDimitry Andric 68020b57cec5SDimitry Andric Result += "\""; 68030b57cec5SDimitry Andric if (Ivars[i]->isBitField()) 68040b57cec5SDimitry Andric RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result); 68050b57cec5SDimitry Andric else 68060b57cec5SDimitry Andric Result += IvarDecl->getName(); 68070b57cec5SDimitry Andric Result += "\", "; 68080b57cec5SDimitry Andric 68090b57cec5SDimitry Andric QualType IVQT = IvarDecl->getType(); 68100b57cec5SDimitry Andric if (IvarDecl->isBitField()) 68110b57cec5SDimitry Andric IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl); 68120b57cec5SDimitry Andric 68130b57cec5SDimitry Andric std::string IvarTypeString, QuoteIvarTypeString; 68140b57cec5SDimitry Andric Context->getObjCEncodingForType(IVQT, IvarTypeString, 68150b57cec5SDimitry Andric IvarDecl); 68160b57cec5SDimitry Andric RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString); 68170b57cec5SDimitry Andric Result += "\""; Result += QuoteIvarTypeString; Result += "\", "; 68180b57cec5SDimitry Andric 68190b57cec5SDimitry Andric // FIXME. this alignment represents the host alignment and need be changed to 68200b57cec5SDimitry Andric // represent the target alignment. 68210b57cec5SDimitry Andric unsigned Align = Context->getTypeAlign(IVQT)/8; 68220b57cec5SDimitry Andric Align = llvm::Log2_32(Align); 68230b57cec5SDimitry Andric Result += llvm::utostr(Align); Result += ", "; 68240b57cec5SDimitry Andric CharUnits Size = Context->getTypeSizeInChars(IVQT); 68250b57cec5SDimitry Andric Result += llvm::utostr(Size.getQuantity()); 68260b57cec5SDimitry Andric if (i == e-1) 68270b57cec5SDimitry Andric Result += "}}\n"; 68280b57cec5SDimitry Andric else 68290b57cec5SDimitry Andric Result += "},\n"; 68300b57cec5SDimitry Andric } 68310b57cec5SDimitry Andric Result += "};\n"; 68320b57cec5SDimitry Andric } 68330b57cec5SDimitry Andric } 68340b57cec5SDimitry Andric 68350b57cec5SDimitry Andric /// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. 68360b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, 68370b57cec5SDimitry Andric std::string &Result) { 68380b57cec5SDimitry Andric 68390b57cec5SDimitry Andric // Do not synthesize the protocol more than once. 68400b57cec5SDimitry Andric if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl())) 68410b57cec5SDimitry Andric return; 68420b57cec5SDimitry Andric WriteModernMetadataDeclarations(Context, Result); 68430b57cec5SDimitry Andric 68440b57cec5SDimitry Andric if (ObjCProtocolDecl *Def = PDecl->getDefinition()) 68450b57cec5SDimitry Andric PDecl = Def; 68460b57cec5SDimitry Andric // Must write out all protocol definitions in current qualifier list, 68470b57cec5SDimitry Andric // and in their nested qualifiers before writing out current definition. 68480b57cec5SDimitry Andric for (auto *I : PDecl->protocols()) 68490b57cec5SDimitry Andric RewriteObjCProtocolMetaData(I, Result); 68500b57cec5SDimitry Andric 68510b57cec5SDimitry Andric // Construct method lists. 68520b57cec5SDimitry Andric std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods; 68530b57cec5SDimitry Andric std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods; 68540b57cec5SDimitry Andric for (auto *MD : PDecl->instance_methods()) { 68555f757f3fSDimitry Andric if (MD->getImplementationControl() == ObjCImplementationControl::Optional) { 68560b57cec5SDimitry Andric OptInstanceMethods.push_back(MD); 68570b57cec5SDimitry Andric } else { 68580b57cec5SDimitry Andric InstanceMethods.push_back(MD); 68590b57cec5SDimitry Andric } 68600b57cec5SDimitry Andric } 68610b57cec5SDimitry Andric 68620b57cec5SDimitry Andric for (auto *MD : PDecl->class_methods()) { 68635f757f3fSDimitry Andric if (MD->getImplementationControl() == ObjCImplementationControl::Optional) { 68640b57cec5SDimitry Andric OptClassMethods.push_back(MD); 68650b57cec5SDimitry Andric } else { 68660b57cec5SDimitry Andric ClassMethods.push_back(MD); 68670b57cec5SDimitry Andric } 68680b57cec5SDimitry Andric } 68690b57cec5SDimitry Andric std::vector<ObjCMethodDecl *> AllMethods; 68700b57cec5SDimitry Andric for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++) 68710b57cec5SDimitry Andric AllMethods.push_back(InstanceMethods[i]); 68720b57cec5SDimitry Andric for (unsigned i = 0, e = ClassMethods.size(); i < e; i++) 68730b57cec5SDimitry Andric AllMethods.push_back(ClassMethods[i]); 68740b57cec5SDimitry Andric for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++) 68750b57cec5SDimitry Andric AllMethods.push_back(OptInstanceMethods[i]); 68760b57cec5SDimitry Andric for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++) 68770b57cec5SDimitry Andric AllMethods.push_back(OptClassMethods[i]); 68780b57cec5SDimitry Andric 68790b57cec5SDimitry Andric Write__extendedMethodTypes_initializer(*this, Context, Result, 68800b57cec5SDimitry Andric AllMethods, 68810b57cec5SDimitry Andric "_OBJC_PROTOCOL_METHOD_TYPES_", 68820b57cec5SDimitry Andric PDecl->getNameAsString()); 68830b57cec5SDimitry Andric // Protocol's super protocol list 68840b57cec5SDimitry Andric SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols()); 68850b57cec5SDimitry Andric Write_protocol_list_initializer(Context, Result, SuperProtocols, 68860b57cec5SDimitry Andric "_OBJC_PROTOCOL_REFS_", 68870b57cec5SDimitry Andric PDecl->getNameAsString()); 68880b57cec5SDimitry Andric 68890b57cec5SDimitry Andric Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 68900b57cec5SDimitry Andric "_OBJC_PROTOCOL_INSTANCE_METHODS_", 68910b57cec5SDimitry Andric PDecl->getNameAsString(), false); 68920b57cec5SDimitry Andric 68930b57cec5SDimitry Andric Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 68940b57cec5SDimitry Andric "_OBJC_PROTOCOL_CLASS_METHODS_", 68950b57cec5SDimitry Andric PDecl->getNameAsString(), false); 68960b57cec5SDimitry Andric 68970b57cec5SDimitry Andric Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods, 68980b57cec5SDimitry Andric "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_", 68990b57cec5SDimitry Andric PDecl->getNameAsString(), false); 69000b57cec5SDimitry Andric 69010b57cec5SDimitry Andric Write_method_list_t_initializer(*this, Context, Result, OptClassMethods, 69020b57cec5SDimitry Andric "_OBJC_PROTOCOL_OPT_CLASS_METHODS_", 69030b57cec5SDimitry Andric PDecl->getNameAsString(), false); 69040b57cec5SDimitry Andric 69050b57cec5SDimitry Andric // Protocol's property metadata. 69060b57cec5SDimitry Andric SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties( 69070b57cec5SDimitry Andric PDecl->instance_properties()); 69080b57cec5SDimitry Andric Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties, 69090b57cec5SDimitry Andric /* Container */nullptr, 69100b57cec5SDimitry Andric "_OBJC_PROTOCOL_PROPERTIES_", 69110b57cec5SDimitry Andric PDecl->getNameAsString()); 69120b57cec5SDimitry Andric 69130b57cec5SDimitry Andric // Writer out root metadata for current protocol: struct _protocol_t 69140b57cec5SDimitry Andric Result += "\n"; 69150b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 69160b57cec5SDimitry Andric Result += "static "; 69170b57cec5SDimitry Andric Result += "struct _protocol_t _OBJC_PROTOCOL_"; 69180b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 69190b57cec5SDimitry Andric Result += " __attribute__ ((used)) = {\n"; 69200b57cec5SDimitry Andric Result += "\t0,\n"; // id is; is null 69210b57cec5SDimitry Andric Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n"; 69220b57cec5SDimitry Andric if (SuperProtocols.size() > 0) { 69230b57cec5SDimitry Andric Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_"; 69240b57cec5SDimitry Andric Result += PDecl->getNameAsString(); Result += ",\n"; 69250b57cec5SDimitry Andric } 69260b57cec5SDimitry Andric else 69270b57cec5SDimitry Andric Result += "\t0,\n"; 69280b57cec5SDimitry Andric if (InstanceMethods.size() > 0) { 69290b57cec5SDimitry Andric Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; 69300b57cec5SDimitry Andric Result += PDecl->getNameAsString(); Result += ",\n"; 69310b57cec5SDimitry Andric } 69320b57cec5SDimitry Andric else 69330b57cec5SDimitry Andric Result += "\t0,\n"; 69340b57cec5SDimitry Andric 69350b57cec5SDimitry Andric if (ClassMethods.size() > 0) { 69360b57cec5SDimitry Andric Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_"; 69370b57cec5SDimitry Andric Result += PDecl->getNameAsString(); Result += ",\n"; 69380b57cec5SDimitry Andric } 69390b57cec5SDimitry Andric else 69400b57cec5SDimitry Andric Result += "\t0,\n"; 69410b57cec5SDimitry Andric 69420b57cec5SDimitry Andric if (OptInstanceMethods.size() > 0) { 69430b57cec5SDimitry Andric Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_"; 69440b57cec5SDimitry Andric Result += PDecl->getNameAsString(); Result += ",\n"; 69450b57cec5SDimitry Andric } 69460b57cec5SDimitry Andric else 69470b57cec5SDimitry Andric Result += "\t0,\n"; 69480b57cec5SDimitry Andric 69490b57cec5SDimitry Andric if (OptClassMethods.size() > 0) { 69500b57cec5SDimitry Andric Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_"; 69510b57cec5SDimitry Andric Result += PDecl->getNameAsString(); Result += ",\n"; 69520b57cec5SDimitry Andric } 69530b57cec5SDimitry Andric else 69540b57cec5SDimitry Andric Result += "\t0,\n"; 69550b57cec5SDimitry Andric 69560b57cec5SDimitry Andric if (ProtocolProperties.size() > 0) { 69570b57cec5SDimitry Andric Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_"; 69580b57cec5SDimitry Andric Result += PDecl->getNameAsString(); Result += ",\n"; 69590b57cec5SDimitry Andric } 69600b57cec5SDimitry Andric else 69610b57cec5SDimitry Andric Result += "\t0,\n"; 69620b57cec5SDimitry Andric 69630b57cec5SDimitry Andric Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n"; 69640b57cec5SDimitry Andric Result += "\t0,\n"; 69650b57cec5SDimitry Andric 69660b57cec5SDimitry Andric if (AllMethods.size() > 0) { 69670b57cec5SDimitry Andric Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_"; 69680b57cec5SDimitry Andric Result += PDecl->getNameAsString(); 69690b57cec5SDimitry Andric Result += "\n};\n"; 69700b57cec5SDimitry Andric } 69710b57cec5SDimitry Andric else 69720b57cec5SDimitry Andric Result += "\t0\n};\n"; 69730b57cec5SDimitry Andric 69740b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 69750b57cec5SDimitry Andric Result += "static "; 69760b57cec5SDimitry Andric Result += "struct _protocol_t *"; 69770b57cec5SDimitry Andric Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString(); 69780b57cec5SDimitry Andric Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString(); 69790b57cec5SDimitry Andric Result += ";\n"; 69800b57cec5SDimitry Andric 69810b57cec5SDimitry Andric // Mark this protocol as having been generated. 69820b57cec5SDimitry Andric if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second) 69830b57cec5SDimitry Andric llvm_unreachable("protocol already synthesized"); 69840b57cec5SDimitry Andric } 69850b57cec5SDimitry Andric 69860b57cec5SDimitry Andric /// hasObjCExceptionAttribute - Return true if this class or any super 69870b57cec5SDimitry Andric /// class has the __objc_exception__ attribute. 69880b57cec5SDimitry Andric /// FIXME. Move this to ASTContext.cpp as it is also used for IRGen. 69890b57cec5SDimitry Andric static bool hasObjCExceptionAttribute(ASTContext &Context, 69900b57cec5SDimitry Andric const ObjCInterfaceDecl *OID) { 69910b57cec5SDimitry Andric if (OID->hasAttr<ObjCExceptionAttr>()) 69920b57cec5SDimitry Andric return true; 69930b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 69940b57cec5SDimitry Andric return hasObjCExceptionAttribute(Context, Super); 69950b57cec5SDimitry Andric return false; 69960b57cec5SDimitry Andric } 69970b57cec5SDimitry Andric 69980b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 69990b57cec5SDimitry Andric std::string &Result) { 70000b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 70010b57cec5SDimitry Andric 70020b57cec5SDimitry Andric // Explicitly declared @interface's are already synthesized. 70030b57cec5SDimitry Andric if (CDecl->isImplicitInterfaceDecl()) 70040b57cec5SDimitry Andric assert(false && 70050b57cec5SDimitry Andric "Legacy implicit interface rewriting not supported in moder abi"); 70060b57cec5SDimitry Andric 70070b57cec5SDimitry Andric WriteModernMetadataDeclarations(Context, Result); 70080b57cec5SDimitry Andric SmallVector<ObjCIvarDecl *, 8> IVars; 70090b57cec5SDimitry Andric 70100b57cec5SDimitry Andric for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 70110b57cec5SDimitry Andric IVD; IVD = IVD->getNextIvar()) { 70120b57cec5SDimitry Andric // Ignore unnamed bit-fields. 70130b57cec5SDimitry Andric if (!IVD->getDeclName()) 70140b57cec5SDimitry Andric continue; 70150b57cec5SDimitry Andric IVars.push_back(IVD); 70160b57cec5SDimitry Andric } 70170b57cec5SDimitry Andric 70180b57cec5SDimitry Andric Write__ivar_list_t_initializer(*this, Context, Result, IVars, 70190b57cec5SDimitry Andric "_OBJC_$_INSTANCE_VARIABLES_", 70200b57cec5SDimitry Andric CDecl); 70210b57cec5SDimitry Andric 70220b57cec5SDimitry Andric // Build _objc_method_list for class's instance methods if needed 70230b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods()); 70240b57cec5SDimitry Andric 70250b57cec5SDimitry Andric // If any of our property implementations have associated getters or 70260b57cec5SDimitry Andric // setters, produce metadata for them as well. 70270b57cec5SDimitry Andric for (const auto *Prop : IDecl->property_impls()) { 70280b57cec5SDimitry Andric if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 70290b57cec5SDimitry Andric continue; 70300b57cec5SDimitry Andric if (!Prop->getPropertyIvarDecl()) 70310b57cec5SDimitry Andric continue; 70320b57cec5SDimitry Andric ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 70330b57cec5SDimitry Andric if (!PD) 70340b57cec5SDimitry Andric continue; 7035480093f4SDimitry Andric if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl()) 70360b57cec5SDimitry Andric if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/)) 70370b57cec5SDimitry Andric InstanceMethods.push_back(Getter); 70380b57cec5SDimitry Andric if (PD->isReadOnly()) 70390b57cec5SDimitry Andric continue; 7040480093f4SDimitry Andric if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl()) 70410b57cec5SDimitry Andric if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/)) 70420b57cec5SDimitry Andric InstanceMethods.push_back(Setter); 70430b57cec5SDimitry Andric } 70440b57cec5SDimitry Andric 70450b57cec5SDimitry Andric Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 70460b57cec5SDimitry Andric "_OBJC_$_INSTANCE_METHODS_", 70470b57cec5SDimitry Andric IDecl->getNameAsString(), true); 70480b57cec5SDimitry Andric 70490b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods()); 70500b57cec5SDimitry Andric 70510b57cec5SDimitry Andric Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 70520b57cec5SDimitry Andric "_OBJC_$_CLASS_METHODS_", 70530b57cec5SDimitry Andric IDecl->getNameAsString(), true); 70540b57cec5SDimitry Andric 70550b57cec5SDimitry Andric // Protocols referenced in class declaration? 70560b57cec5SDimitry Andric // Protocol's super protocol list 70570b57cec5SDimitry Andric std::vector<ObjCProtocolDecl *> RefedProtocols; 70580b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols(); 70590b57cec5SDimitry Andric for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 70600b57cec5SDimitry Andric E = Protocols.end(); 70610b57cec5SDimitry Andric I != E; ++I) { 70620b57cec5SDimitry Andric RefedProtocols.push_back(*I); 70630b57cec5SDimitry Andric // Must write out all protocol definitions in current qualifier list, 70640b57cec5SDimitry Andric // and in their nested qualifiers before writing out current definition. 70650b57cec5SDimitry Andric RewriteObjCProtocolMetaData(*I, Result); 70660b57cec5SDimitry Andric } 70670b57cec5SDimitry Andric 70680b57cec5SDimitry Andric Write_protocol_list_initializer(Context, Result, 70690b57cec5SDimitry Andric RefedProtocols, 70700b57cec5SDimitry Andric "_OBJC_CLASS_PROTOCOLS_$_", 70710b57cec5SDimitry Andric IDecl->getNameAsString()); 70720b57cec5SDimitry Andric 70730b57cec5SDimitry Andric // Protocol's property metadata. 70740b57cec5SDimitry Andric SmallVector<ObjCPropertyDecl *, 8> ClassProperties( 70750b57cec5SDimitry Andric CDecl->instance_properties()); 70760b57cec5SDimitry Andric Write_prop_list_t_initializer(*this, Context, Result, ClassProperties, 70770b57cec5SDimitry Andric /* Container */IDecl, 70780b57cec5SDimitry Andric "_OBJC_$_PROP_LIST_", 70790b57cec5SDimitry Andric CDecl->getNameAsString()); 70800b57cec5SDimitry Andric 70810b57cec5SDimitry Andric // Data for initializing _class_ro_t metaclass meta-data 70820b57cec5SDimitry Andric uint32_t flags = CLS_META; 70830b57cec5SDimitry Andric std::string InstanceSize; 70840b57cec5SDimitry Andric std::string InstanceStart; 70850b57cec5SDimitry Andric 70860b57cec5SDimitry Andric bool classIsHidden = CDecl->getVisibility() == HiddenVisibility; 70870b57cec5SDimitry Andric if (classIsHidden) 70880b57cec5SDimitry Andric flags |= OBJC2_CLS_HIDDEN; 70890b57cec5SDimitry Andric 70900b57cec5SDimitry Andric if (!CDecl->getSuperClass()) 70910b57cec5SDimitry Andric // class is root 70920b57cec5SDimitry Andric flags |= CLS_ROOT; 70930b57cec5SDimitry Andric InstanceSize = "sizeof(struct _class_t)"; 70940b57cec5SDimitry Andric InstanceStart = InstanceSize; 70950b57cec5SDimitry Andric Write__class_ro_t_initializer(Context, Result, flags, 70960b57cec5SDimitry Andric InstanceStart, InstanceSize, 70970b57cec5SDimitry Andric ClassMethods, 70980b57cec5SDimitry Andric nullptr, 70990b57cec5SDimitry Andric nullptr, 71000b57cec5SDimitry Andric nullptr, 71010b57cec5SDimitry Andric "_OBJC_METACLASS_RO_$_", 71020b57cec5SDimitry Andric CDecl->getNameAsString()); 71030b57cec5SDimitry Andric 71040b57cec5SDimitry Andric // Data for initializing _class_ro_t meta-data 71050b57cec5SDimitry Andric flags = CLS; 71060b57cec5SDimitry Andric if (classIsHidden) 71070b57cec5SDimitry Andric flags |= OBJC2_CLS_HIDDEN; 71080b57cec5SDimitry Andric 71090b57cec5SDimitry Andric if (hasObjCExceptionAttribute(*Context, CDecl)) 71100b57cec5SDimitry Andric flags |= CLS_EXCEPTION; 71110b57cec5SDimitry Andric 71120b57cec5SDimitry Andric if (!CDecl->getSuperClass()) 71130b57cec5SDimitry Andric // class is root 71140b57cec5SDimitry Andric flags |= CLS_ROOT; 71150b57cec5SDimitry Andric 71160b57cec5SDimitry Andric InstanceSize.clear(); 71170b57cec5SDimitry Andric InstanceStart.clear(); 71180b57cec5SDimitry Andric if (!ObjCSynthesizedStructs.count(CDecl)) { 71190b57cec5SDimitry Andric InstanceSize = "0"; 71200b57cec5SDimitry Andric InstanceStart = "0"; 71210b57cec5SDimitry Andric } 71220b57cec5SDimitry Andric else { 71230b57cec5SDimitry Andric InstanceSize = "sizeof(struct "; 71240b57cec5SDimitry Andric InstanceSize += CDecl->getNameAsString(); 71250b57cec5SDimitry Andric InstanceSize += "_IMPL)"; 71260b57cec5SDimitry Andric 71270b57cec5SDimitry Andric ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 71280b57cec5SDimitry Andric if (IVD) { 71290b57cec5SDimitry Andric RewriteIvarOffsetComputation(IVD, InstanceStart); 71300b57cec5SDimitry Andric } 71310b57cec5SDimitry Andric else 71320b57cec5SDimitry Andric InstanceStart = InstanceSize; 71330b57cec5SDimitry Andric } 71340b57cec5SDimitry Andric Write__class_ro_t_initializer(Context, Result, flags, 71350b57cec5SDimitry Andric InstanceStart, InstanceSize, 71360b57cec5SDimitry Andric InstanceMethods, 71370b57cec5SDimitry Andric RefedProtocols, 71380b57cec5SDimitry Andric IVars, 71390b57cec5SDimitry Andric ClassProperties, 71400b57cec5SDimitry Andric "_OBJC_CLASS_RO_$_", 71410b57cec5SDimitry Andric CDecl->getNameAsString()); 71420b57cec5SDimitry Andric 71430b57cec5SDimitry Andric Write_class_t(Context, Result, 71440b57cec5SDimitry Andric "OBJC_METACLASS_$_", 71450b57cec5SDimitry Andric CDecl, /*metaclass*/true); 71460b57cec5SDimitry Andric 71470b57cec5SDimitry Andric Write_class_t(Context, Result, 71480b57cec5SDimitry Andric "OBJC_CLASS_$_", 71490b57cec5SDimitry Andric CDecl, /*metaclass*/false); 71500b57cec5SDimitry Andric 71510b57cec5SDimitry Andric if (ImplementationIsNonLazy(IDecl)) 71520b57cec5SDimitry Andric DefinedNonLazyClasses.push_back(CDecl); 71530b57cec5SDimitry Andric } 71540b57cec5SDimitry Andric 71550b57cec5SDimitry Andric void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) { 71560b57cec5SDimitry Andric int ClsDefCount = ClassImplementation.size(); 71570b57cec5SDimitry Andric if (!ClsDefCount) 71580b57cec5SDimitry Andric return; 71590b57cec5SDimitry Andric Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n"; 71600b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_inithooks$B\")) "; 71610b57cec5SDimitry Andric Result += "static void *OBJC_CLASS_SETUP[] = {\n"; 71620b57cec5SDimitry Andric for (int i = 0; i < ClsDefCount; i++) { 71630b57cec5SDimitry Andric ObjCImplementationDecl *IDecl = ClassImplementation[i]; 71640b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 71650b57cec5SDimitry Andric Result += "\t(void *)&OBJC_CLASS_SETUP_$_"; 71660b57cec5SDimitry Andric Result += CDecl->getName(); Result += ",\n"; 71670b57cec5SDimitry Andric } 71680b57cec5SDimitry Andric Result += "};\n"; 71690b57cec5SDimitry Andric } 71700b57cec5SDimitry Andric 71710b57cec5SDimitry Andric void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) { 71720b57cec5SDimitry Andric int ClsDefCount = ClassImplementation.size(); 71730b57cec5SDimitry Andric int CatDefCount = CategoryImplementation.size(); 71740b57cec5SDimitry Andric 71750b57cec5SDimitry Andric // For each implemented class, write out all its meta data. 71760b57cec5SDimitry Andric for (int i = 0; i < ClsDefCount; i++) 71770b57cec5SDimitry Andric RewriteObjCClassMetaData(ClassImplementation[i], Result); 71780b57cec5SDimitry Andric 71790b57cec5SDimitry Andric RewriteClassSetupInitHook(Result); 71800b57cec5SDimitry Andric 71810b57cec5SDimitry Andric // For each implemented category, write out all its meta data. 71820b57cec5SDimitry Andric for (int i = 0; i < CatDefCount; i++) 71830b57cec5SDimitry Andric RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); 71840b57cec5SDimitry Andric 71850b57cec5SDimitry Andric RewriteCategorySetupInitHook(Result); 71860b57cec5SDimitry Andric 71870b57cec5SDimitry Andric if (ClsDefCount > 0) { 71880b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 71890b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_classlist$B\")) "; 71900b57cec5SDimitry Andric Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ ["; 71910b57cec5SDimitry Andric Result += llvm::utostr(ClsDefCount); Result += "]"; 71920b57cec5SDimitry Andric Result += 71930b57cec5SDimitry Andric " __attribute__((used, section (\"__DATA, __objc_classlist," 71940b57cec5SDimitry Andric "regular,no_dead_strip\")))= {\n"; 71950b57cec5SDimitry Andric for (int i = 0; i < ClsDefCount; i++) { 71960b57cec5SDimitry Andric Result += "\t&OBJC_CLASS_$_"; 71970b57cec5SDimitry Andric Result += ClassImplementation[i]->getNameAsString(); 71980b57cec5SDimitry Andric Result += ",\n"; 71990b57cec5SDimitry Andric } 72000b57cec5SDimitry Andric Result += "};\n"; 72010b57cec5SDimitry Andric 72020b57cec5SDimitry Andric if (!DefinedNonLazyClasses.empty()) { 72030b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 72040b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n"; 72050b57cec5SDimitry Andric Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t"; 72060b57cec5SDimitry Andric for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) { 72070b57cec5SDimitry Andric Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString(); 72080b57cec5SDimitry Andric Result += ",\n"; 72090b57cec5SDimitry Andric } 72100b57cec5SDimitry Andric Result += "};\n"; 72110b57cec5SDimitry Andric } 72120b57cec5SDimitry Andric } 72130b57cec5SDimitry Andric 72140b57cec5SDimitry Andric if (CatDefCount > 0) { 72150b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 72160b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_catlist$B\")) "; 72170b57cec5SDimitry Andric Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ ["; 72180b57cec5SDimitry Andric Result += llvm::utostr(CatDefCount); Result += "]"; 72190b57cec5SDimitry Andric Result += 72200b57cec5SDimitry Andric " __attribute__((used, section (\"__DATA, __objc_catlist," 72210b57cec5SDimitry Andric "regular,no_dead_strip\")))= {\n"; 72220b57cec5SDimitry Andric for (int i = 0; i < CatDefCount; i++) { 72230b57cec5SDimitry Andric Result += "\t&_OBJC_$_CATEGORY_"; 72240b57cec5SDimitry Andric Result += 72250b57cec5SDimitry Andric CategoryImplementation[i]->getClassInterface()->getNameAsString(); 72260b57cec5SDimitry Andric Result += "_$_"; 72270b57cec5SDimitry Andric Result += CategoryImplementation[i]->getNameAsString(); 72280b57cec5SDimitry Andric Result += ",\n"; 72290b57cec5SDimitry Andric } 72300b57cec5SDimitry Andric Result += "};\n"; 72310b57cec5SDimitry Andric } 72320b57cec5SDimitry Andric 72330b57cec5SDimitry Andric if (!DefinedNonLazyCategories.empty()) { 72340b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 72350b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n"; 72360b57cec5SDimitry Andric Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t"; 72370b57cec5SDimitry Andric for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) { 72380b57cec5SDimitry Andric Result += "\t&_OBJC_$_CATEGORY_"; 72390b57cec5SDimitry Andric Result += 72400b57cec5SDimitry Andric DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString(); 72410b57cec5SDimitry Andric Result += "_$_"; 72420b57cec5SDimitry Andric Result += DefinedNonLazyCategories[i]->getNameAsString(); 72430b57cec5SDimitry Andric Result += ",\n"; 72440b57cec5SDimitry Andric } 72450b57cec5SDimitry Andric Result += "};\n"; 72460b57cec5SDimitry Andric } 72470b57cec5SDimitry Andric } 72480b57cec5SDimitry Andric 72490b57cec5SDimitry Andric void RewriteModernObjC::WriteImageInfo(std::string &Result) { 72500b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) 72510b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n"; 72520b57cec5SDimitry Andric 72530b57cec5SDimitry Andric Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } "; 72540b57cec5SDimitry Andric // version 0, ObjCABI is 2 72550b57cec5SDimitry Andric Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n"; 72560b57cec5SDimitry Andric } 72570b57cec5SDimitry Andric 72580b57cec5SDimitry Andric /// RewriteObjCCategoryImplDecl - Rewrite metadata for each category 72590b57cec5SDimitry Andric /// implementation. 72600b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, 72610b57cec5SDimitry Andric std::string &Result) { 72620b57cec5SDimitry Andric WriteModernMetadataDeclarations(Context, Result); 72630b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 72640b57cec5SDimitry Andric // Find category declaration for this implementation. 72650b57cec5SDimitry Andric ObjCCategoryDecl *CDecl 72660b57cec5SDimitry Andric = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier()); 72670b57cec5SDimitry Andric 72680b57cec5SDimitry Andric std::string FullCategoryName = ClassDecl->getNameAsString(); 72690b57cec5SDimitry Andric FullCategoryName += "_$_"; 72700b57cec5SDimitry Andric FullCategoryName += CDecl->getNameAsString(); 72710b57cec5SDimitry Andric 72720b57cec5SDimitry Andric // Build _objc_method_list for class's instance methods if needed 72730b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods()); 72740b57cec5SDimitry Andric 72750b57cec5SDimitry Andric // If any of our property implementations have associated getters or 72760b57cec5SDimitry Andric // setters, produce metadata for them as well. 72770b57cec5SDimitry Andric for (const auto *Prop : IDecl->property_impls()) { 72780b57cec5SDimitry Andric if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 72790b57cec5SDimitry Andric continue; 72800b57cec5SDimitry Andric if (!Prop->getPropertyIvarDecl()) 72810b57cec5SDimitry Andric continue; 72820b57cec5SDimitry Andric ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 72830b57cec5SDimitry Andric if (!PD) 72840b57cec5SDimitry Andric continue; 7285480093f4SDimitry Andric if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl()) 72860b57cec5SDimitry Andric InstanceMethods.push_back(Getter); 72870b57cec5SDimitry Andric if (PD->isReadOnly()) 72880b57cec5SDimitry Andric continue; 7289480093f4SDimitry Andric if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl()) 72900b57cec5SDimitry Andric InstanceMethods.push_back(Setter); 72910b57cec5SDimitry Andric } 72920b57cec5SDimitry Andric 72930b57cec5SDimitry Andric Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 72940b57cec5SDimitry Andric "_OBJC_$_CATEGORY_INSTANCE_METHODS_", 72950b57cec5SDimitry Andric FullCategoryName, true); 72960b57cec5SDimitry Andric 72970b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods()); 72980b57cec5SDimitry Andric 72990b57cec5SDimitry Andric Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 73000b57cec5SDimitry Andric "_OBJC_$_CATEGORY_CLASS_METHODS_", 73010b57cec5SDimitry Andric FullCategoryName, true); 73020b57cec5SDimitry Andric 73030b57cec5SDimitry Andric // Protocols referenced in class declaration? 73040b57cec5SDimitry Andric // Protocol's super protocol list 73050b57cec5SDimitry Andric SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols()); 73060b57cec5SDimitry Andric for (auto *I : CDecl->protocols()) 73070b57cec5SDimitry Andric // Must write out all protocol definitions in current qualifier list, 73080b57cec5SDimitry Andric // and in their nested qualifiers before writing out current definition. 73090b57cec5SDimitry Andric RewriteObjCProtocolMetaData(I, Result); 73100b57cec5SDimitry Andric 73110b57cec5SDimitry Andric Write_protocol_list_initializer(Context, Result, 73120b57cec5SDimitry Andric RefedProtocols, 73130b57cec5SDimitry Andric "_OBJC_CATEGORY_PROTOCOLS_$_", 73140b57cec5SDimitry Andric FullCategoryName); 73150b57cec5SDimitry Andric 73160b57cec5SDimitry Andric // Protocol's property metadata. 73170b57cec5SDimitry Andric SmallVector<ObjCPropertyDecl *, 8> ClassProperties( 73180b57cec5SDimitry Andric CDecl->instance_properties()); 73190b57cec5SDimitry Andric Write_prop_list_t_initializer(*this, Context, Result, ClassProperties, 73200b57cec5SDimitry Andric /* Container */IDecl, 73210b57cec5SDimitry Andric "_OBJC_$_PROP_LIST_", 73220b57cec5SDimitry Andric FullCategoryName); 73230b57cec5SDimitry Andric 73240b57cec5SDimitry Andric Write_category_t(*this, Context, Result, 73250b57cec5SDimitry Andric CDecl, 73260b57cec5SDimitry Andric ClassDecl, 73270b57cec5SDimitry Andric InstanceMethods, 73280b57cec5SDimitry Andric ClassMethods, 73290b57cec5SDimitry Andric RefedProtocols, 73300b57cec5SDimitry Andric ClassProperties); 73310b57cec5SDimitry Andric 73320b57cec5SDimitry Andric // Determine if this category is also "non-lazy". 73330b57cec5SDimitry Andric if (ImplementationIsNonLazy(IDecl)) 73340b57cec5SDimitry Andric DefinedNonLazyCategories.push_back(CDecl); 73350b57cec5SDimitry Andric } 73360b57cec5SDimitry Andric 73370b57cec5SDimitry Andric void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) { 73380b57cec5SDimitry Andric int CatDefCount = CategoryImplementation.size(); 73390b57cec5SDimitry Andric if (!CatDefCount) 73400b57cec5SDimitry Andric return; 73410b57cec5SDimitry Andric Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n"; 73420b57cec5SDimitry Andric Result += "__declspec(allocate(\".objc_inithooks$B\")) "; 73430b57cec5SDimitry Andric Result += "static void *OBJC_CATEGORY_SETUP[] = {\n"; 73440b57cec5SDimitry Andric for (int i = 0; i < CatDefCount; i++) { 73450b57cec5SDimitry Andric ObjCCategoryImplDecl *IDecl = CategoryImplementation[i]; 73460b57cec5SDimitry Andric ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl(); 73470b57cec5SDimitry Andric ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 73480b57cec5SDimitry Andric Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_"; 73490b57cec5SDimitry Andric Result += ClassDecl->getName(); 73500b57cec5SDimitry Andric Result += "_$_"; 73510b57cec5SDimitry Andric Result += CatDecl->getName(); 73520b57cec5SDimitry Andric Result += ",\n"; 73530b57cec5SDimitry Andric } 73540b57cec5SDimitry Andric Result += "};\n"; 73550b57cec5SDimitry Andric } 73560b57cec5SDimitry Andric 73570b57cec5SDimitry Andric // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or 73580b57cec5SDimitry Andric /// class methods. 73590b57cec5SDimitry Andric template<typename MethodIterator> 73600b57cec5SDimitry Andric void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 73610b57cec5SDimitry Andric MethodIterator MethodEnd, 73620b57cec5SDimitry Andric bool IsInstanceMethod, 73630b57cec5SDimitry Andric StringRef prefix, 73640b57cec5SDimitry Andric StringRef ClassName, 73650b57cec5SDimitry Andric std::string &Result) { 73660b57cec5SDimitry Andric if (MethodBegin == MethodEnd) return; 73670b57cec5SDimitry Andric 73680b57cec5SDimitry Andric if (!objc_impl_method) { 73690b57cec5SDimitry Andric /* struct _objc_method { 73700b57cec5SDimitry Andric SEL _cmd; 73710b57cec5SDimitry Andric char *method_types; 73720b57cec5SDimitry Andric void *_imp; 73730b57cec5SDimitry Andric } 73740b57cec5SDimitry Andric */ 73750b57cec5SDimitry Andric Result += "\nstruct _objc_method {\n"; 73760b57cec5SDimitry Andric Result += "\tSEL _cmd;\n"; 73770b57cec5SDimitry Andric Result += "\tchar *method_types;\n"; 73780b57cec5SDimitry Andric Result += "\tvoid *_imp;\n"; 73790b57cec5SDimitry Andric Result += "};\n"; 73800b57cec5SDimitry Andric 73810b57cec5SDimitry Andric objc_impl_method = true; 73820b57cec5SDimitry Andric } 73830b57cec5SDimitry Andric 73840b57cec5SDimitry Andric // Build _objc_method_list for class's methods if needed 73850b57cec5SDimitry Andric 73860b57cec5SDimitry Andric /* struct { 73870b57cec5SDimitry Andric struct _objc_method_list *next_method; 73880b57cec5SDimitry Andric int method_count; 73890b57cec5SDimitry Andric struct _objc_method method_list[]; 73900b57cec5SDimitry Andric } 73910b57cec5SDimitry Andric */ 73920b57cec5SDimitry Andric unsigned NumMethods = std::distance(MethodBegin, MethodEnd); 73930b57cec5SDimitry Andric Result += "\n"; 73940b57cec5SDimitry Andric if (LangOpts.MicrosoftExt) { 73950b57cec5SDimitry Andric if (IsInstanceMethod) 73960b57cec5SDimitry Andric Result += "__declspec(allocate(\".inst_meth$B\")) "; 73970b57cec5SDimitry Andric else 73980b57cec5SDimitry Andric Result += "__declspec(allocate(\".cls_meth$B\")) "; 73990b57cec5SDimitry Andric } 74000b57cec5SDimitry Andric Result += "static struct {\n"; 74010b57cec5SDimitry Andric Result += "\tstruct _objc_method_list *next_method;\n"; 74020b57cec5SDimitry Andric Result += "\tint method_count;\n"; 74030b57cec5SDimitry Andric Result += "\tstruct _objc_method method_list["; 74040b57cec5SDimitry Andric Result += utostr(NumMethods); 74050b57cec5SDimitry Andric Result += "];\n} _OBJC_"; 74060b57cec5SDimitry Andric Result += prefix; 74070b57cec5SDimitry Andric Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; 74080b57cec5SDimitry Andric Result += "_METHODS_"; 74090b57cec5SDimitry Andric Result += ClassName; 74100b57cec5SDimitry Andric Result += " __attribute__ ((used, section (\"__OBJC, __"; 74110b57cec5SDimitry Andric Result += IsInstanceMethod ? "inst" : "cls"; 74120b57cec5SDimitry Andric Result += "_meth\")))= "; 74130b57cec5SDimitry Andric Result += "{\n\t0, " + utostr(NumMethods) + "\n"; 74140b57cec5SDimitry Andric 74150b57cec5SDimitry Andric Result += "\t,{{(SEL)\""; 74160b57cec5SDimitry Andric Result += (*MethodBegin)->getSelector().getAsString().c_str(); 74170b57cec5SDimitry Andric std::string MethodTypeString; 74180b57cec5SDimitry Andric Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 74190b57cec5SDimitry Andric Result += "\", \""; 74200b57cec5SDimitry Andric Result += MethodTypeString; 74210b57cec5SDimitry Andric Result += "\", (void *)"; 74220b57cec5SDimitry Andric Result += MethodInternalNames[*MethodBegin]; 74230b57cec5SDimitry Andric Result += "}\n"; 74240b57cec5SDimitry Andric for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { 74250b57cec5SDimitry Andric Result += "\t ,{(SEL)\""; 74260b57cec5SDimitry Andric Result += (*MethodBegin)->getSelector().getAsString().c_str(); 74270b57cec5SDimitry Andric std::string MethodTypeString; 74280b57cec5SDimitry Andric Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 74290b57cec5SDimitry Andric Result += "\", \""; 74300b57cec5SDimitry Andric Result += MethodTypeString; 74310b57cec5SDimitry Andric Result += "\", (void *)"; 74320b57cec5SDimitry Andric Result += MethodInternalNames[*MethodBegin]; 74330b57cec5SDimitry Andric Result += "}\n"; 74340b57cec5SDimitry Andric } 74350b57cec5SDimitry Andric Result += "\t }\n};\n"; 74360b57cec5SDimitry Andric } 74370b57cec5SDimitry Andric 74380b57cec5SDimitry Andric Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { 74390b57cec5SDimitry Andric SourceRange OldRange = IV->getSourceRange(); 74400b57cec5SDimitry Andric Expr *BaseExpr = IV->getBase(); 74410b57cec5SDimitry Andric 74420b57cec5SDimitry Andric // Rewrite the base, but without actually doing replaces. 74430b57cec5SDimitry Andric { 74440b57cec5SDimitry Andric DisableReplaceStmtScope S(*this); 74450b57cec5SDimitry Andric BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr)); 74460b57cec5SDimitry Andric IV->setBase(BaseExpr); 74470b57cec5SDimitry Andric } 74480b57cec5SDimitry Andric 74490b57cec5SDimitry Andric ObjCIvarDecl *D = IV->getDecl(); 74500b57cec5SDimitry Andric 74510b57cec5SDimitry Andric Expr *Replacement = IV; 74520b57cec5SDimitry Andric 74530b57cec5SDimitry Andric if (BaseExpr->getType()->isObjCObjectPointerType()) { 74540b57cec5SDimitry Andric const ObjCInterfaceType *iFaceDecl = 74550b57cec5SDimitry Andric dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 74560b57cec5SDimitry Andric assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); 74570b57cec5SDimitry Andric // lookup which class implements the instance variable. 74580b57cec5SDimitry Andric ObjCInterfaceDecl *clsDeclared = nullptr; 74590b57cec5SDimitry Andric iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 74600b57cec5SDimitry Andric clsDeclared); 74610b57cec5SDimitry Andric assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 74620b57cec5SDimitry Andric 74630b57cec5SDimitry Andric // Build name of symbol holding ivar offset. 74640b57cec5SDimitry Andric std::string IvarOffsetName; 74650b57cec5SDimitry Andric if (D->isBitField()) 74660b57cec5SDimitry Andric ObjCIvarBitfieldGroupOffset(D, IvarOffsetName); 74670b57cec5SDimitry Andric else 74680b57cec5SDimitry Andric WriteInternalIvarName(clsDeclared, D, IvarOffsetName); 74690b57cec5SDimitry Andric 74700b57cec5SDimitry Andric ReferencedIvars[clsDeclared].insert(D); 74710b57cec5SDimitry Andric 74720b57cec5SDimitry Andric // cast offset to "char *". 74730b57cec5SDimitry Andric CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, 74740b57cec5SDimitry Andric Context->getPointerType(Context->CharTy), 74750b57cec5SDimitry Andric CK_BitCast, 74760b57cec5SDimitry Andric BaseExpr); 74770b57cec5SDimitry Andric VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 74780b57cec5SDimitry Andric SourceLocation(), &Context->Idents.get(IvarOffsetName), 74790b57cec5SDimitry Andric Context->UnsignedLongTy, nullptr, 74800b57cec5SDimitry Andric SC_Extern); 74810b57cec5SDimitry Andric DeclRefExpr *DRE = new (Context) 74820b57cec5SDimitry Andric DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy, 74830b57cec5SDimitry Andric VK_LValue, SourceLocation()); 74845ffd83dbSDimitry Andric BinaryOperator *addExpr = BinaryOperator::Create( 74855ffd83dbSDimitry Andric *Context, castExpr, DRE, BO_Add, 7486fe6060f1SDimitry Andric Context->getPointerType(Context->CharTy), VK_PRValue, OK_Ordinary, 74875ffd83dbSDimitry Andric SourceLocation(), FPOptionsOverride()); 74880b57cec5SDimitry Andric // Don't forget the parens to enforce the proper binding. 74890b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), 74900b57cec5SDimitry Andric SourceLocation(), 74910b57cec5SDimitry Andric addExpr); 74920b57cec5SDimitry Andric QualType IvarT = D->getType(); 74930b57cec5SDimitry Andric if (D->isBitField()) 74940b57cec5SDimitry Andric IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); 74950b57cec5SDimitry Andric 7496bdd1243dSDimitry Andric if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) { 7497a7dea167SDimitry Andric RecordDecl *RD = IvarT->castAs<RecordType>()->getDecl(); 74980b57cec5SDimitry Andric RD = RD->getDefinition(); 74990b57cec5SDimitry Andric if (RD && !RD->getDeclName().getAsIdentifierInfo()) { 75000b57cec5SDimitry Andric // decltype(((Foo_IMPL*)0)->bar) * 75015ffd83dbSDimitry Andric auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext()); 75020b57cec5SDimitry Andric // ivar in class extensions requires special treatment. 75030b57cec5SDimitry Andric if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 75040b57cec5SDimitry Andric CDecl = CatDecl->getClassInterface(); 75055ffd83dbSDimitry Andric std::string RecName = std::string(CDecl->getName()); 75060b57cec5SDimitry Andric RecName += "_IMPL"; 75070b57cec5SDimitry Andric RecordDecl *RD = RecordDecl::Create( 75085f757f3fSDimitry Andric *Context, TagTypeKind::Struct, TUDecl, SourceLocation(), 75095f757f3fSDimitry Andric SourceLocation(), &Context->Idents.get(RecName)); 75100b57cec5SDimitry Andric QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD)); 75110b57cec5SDimitry Andric unsigned UnsignedIntSize = 75120b57cec5SDimitry Andric static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 75130b57cec5SDimitry Andric Expr *Zero = IntegerLiteral::Create(*Context, 75140b57cec5SDimitry Andric llvm::APInt(UnsignedIntSize, 0), 75150b57cec5SDimitry Andric Context->UnsignedIntTy, SourceLocation()); 75160b57cec5SDimitry Andric Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero); 75170b57cec5SDimitry Andric ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 75180b57cec5SDimitry Andric Zero); 75190b57cec5SDimitry Andric FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 75200b57cec5SDimitry Andric SourceLocation(), 75210b57cec5SDimitry Andric &Context->Idents.get(D->getNameAsString()), 75220b57cec5SDimitry Andric IvarT, nullptr, 75230b57cec5SDimitry Andric /*BitWidth=*/nullptr, 75240b57cec5SDimitry Andric /*Mutable=*/true, ICIS_NoInit); 75250b57cec5SDimitry Andric MemberExpr *ME = MemberExpr::CreateImplicit( 75260b57cec5SDimitry Andric *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary); 75270b57cec5SDimitry Andric IvarT = Context->getDecltypeType(ME, ME->getType()); 75280b57cec5SDimitry Andric } 75290b57cec5SDimitry Andric } 75300b57cec5SDimitry Andric convertObjCTypeToCStyleType(IvarT); 75310b57cec5SDimitry Andric QualType castT = Context->getPointerType(IvarT); 75320b57cec5SDimitry Andric 75330b57cec5SDimitry Andric castExpr = NoTypeInfoCStyleCastExpr(Context, 75340b57cec5SDimitry Andric castT, 75350b57cec5SDimitry Andric CK_BitCast, 75360b57cec5SDimitry Andric PE); 75370b57cec5SDimitry Andric 75385ffd83dbSDimitry Andric Expr *Exp = UnaryOperator::Create( 75395ffd83dbSDimitry Andric const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT, 75405ffd83dbSDimitry Andric VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride()); 75410b57cec5SDimitry Andric PE = new (Context) ParenExpr(OldRange.getBegin(), 75420b57cec5SDimitry Andric OldRange.getEnd(), 75430b57cec5SDimitry Andric Exp); 75440b57cec5SDimitry Andric 75450b57cec5SDimitry Andric if (D->isBitField()) { 75460b57cec5SDimitry Andric FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), 75470b57cec5SDimitry Andric SourceLocation(), 75480b57cec5SDimitry Andric &Context->Idents.get(D->getNameAsString()), 75490b57cec5SDimitry Andric D->getType(), nullptr, 75500b57cec5SDimitry Andric /*BitWidth=*/D->getBitWidth(), 75510b57cec5SDimitry Andric /*Mutable=*/true, ICIS_NoInit); 75520b57cec5SDimitry Andric MemberExpr *ME = 75530b57cec5SDimitry Andric MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD, 75540b57cec5SDimitry Andric FD->getType(), VK_LValue, OK_Ordinary); 75550b57cec5SDimitry Andric Replacement = ME; 75560b57cec5SDimitry Andric 75570b57cec5SDimitry Andric } 75580b57cec5SDimitry Andric else 75590b57cec5SDimitry Andric Replacement = PE; 75600b57cec5SDimitry Andric } 75610b57cec5SDimitry Andric 75620b57cec5SDimitry Andric ReplaceStmtWithRange(IV, Replacement, OldRange); 75630b57cec5SDimitry Andric return Replacement; 75640b57cec5SDimitry Andric } 75650b57cec5SDimitry Andric 75660b57cec5SDimitry Andric #endif // CLANG_ENABLE_OBJC_REWRITER 7567