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