5870 lines · cpp
1//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Hacks and fun related to the code rewriter.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Rewrite/Frontend/ASTConsumers.h"14#include "clang/AST/AST.h"15#include "clang/AST/ASTConsumer.h"16#include "clang/AST/Attr.h"17#include "clang/AST/ParentMap.h"18#include "clang/Basic/CharInfo.h"19#include "clang/Basic/Diagnostic.h"20#include "clang/Basic/IdentifierTable.h"21#include "clang/Basic/SourceManager.h"22#include "clang/Config/config.h"23#include "clang/Lex/Lexer.h"24#include "clang/Rewrite/Core/Rewriter.h"25#include "llvm/ADT/DenseSet.h"26#include "llvm/ADT/SmallPtrSet.h"27#include "llvm/ADT/StringExtras.h"28#include "llvm/Support/MemoryBuffer.h"29#include "llvm/Support/raw_ostream.h"30#include <memory>31 32#if CLANG_ENABLE_OBJC_REWRITER33 34using namespace clang;35using llvm::RewriteBuffer;36using llvm::utostr;37 38namespace {39 class RewriteObjC : public ASTConsumer {40 protected:41 enum {42 BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),43 block, ... */44 BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */45 BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the46 __block variable */47 BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy48 helpers */49 BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose50 support routines */51 BLOCK_BYREF_CURRENT_MAX = 25652 };53 54 enum {55 BLOCK_NEEDS_FREE = (1 << 24),56 BLOCK_HAS_COPY_DISPOSE = (1 << 25),57 BLOCK_HAS_CXX_OBJ = (1 << 26),58 BLOCK_IS_GC = (1 << 27),59 BLOCK_IS_GLOBAL = (1 << 28),60 BLOCK_HAS_DESCRIPTOR = (1 << 29)61 };62 static const int OBJC_ABI_VERSION = 7;63 64 Rewriter Rewrite;65 DiagnosticsEngine &Diags;66 const LangOptions &LangOpts;67 ASTContext *Context;68 SourceManager *SM;69 TranslationUnitDecl *TUDecl;70 FileID MainFileID;71 const char *MainFileStart, *MainFileEnd;72 Stmt *CurrentBody;73 ParentMap *PropParentMap; // created lazily.74 std::string InFileName;75 std::unique_ptr<raw_ostream> OutFile;76 std::string Preamble;77 78 TypeDecl *ProtocolTypeDecl;79 VarDecl *GlobalVarDecl;80 unsigned RewriteFailedDiag;81 // ObjC string constant support.82 unsigned NumObjCStringLiterals;83 VarDecl *ConstantStringClassReference;84 RecordDecl *NSStringRecord;85 86 // ObjC foreach break/continue generation support.87 int BcLabelCount;88 89 unsigned TryFinallyContainsReturnDiag;90 // Needed for super.91 ObjCMethodDecl *CurMethodDef;92 RecordDecl *SuperStructDecl;93 RecordDecl *ConstantStringDecl;94 95 FunctionDecl *MsgSendFunctionDecl;96 FunctionDecl *MsgSendSuperFunctionDecl;97 FunctionDecl *MsgSendStretFunctionDecl;98 FunctionDecl *MsgSendSuperStretFunctionDecl;99 FunctionDecl *MsgSendFpretFunctionDecl;100 FunctionDecl *GetClassFunctionDecl;101 FunctionDecl *GetMetaClassFunctionDecl;102 FunctionDecl *GetSuperClassFunctionDecl;103 FunctionDecl *SelGetUidFunctionDecl;104 FunctionDecl *CFStringFunctionDecl;105 FunctionDecl *SuperConstructorFunctionDecl;106 FunctionDecl *CurFunctionDef;107 FunctionDecl *CurFunctionDeclToDeclareForBlock;108 109 /* Misc. containers needed for meta-data rewrite. */110 SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;111 SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;112 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;113 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;114 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;115 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;116 SmallVector<Stmt *, 32> Stmts;117 SmallVector<int, 8> ObjCBcLabelNo;118 // Remember all the @protocol(<expr>) expressions.119 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;120 121 llvm::DenseSet<uint64_t> CopyDestroyCache;122 123 // Block expressions.124 SmallVector<BlockExpr *, 32> Blocks;125 SmallVector<int, 32> InnerDeclRefsCount;126 SmallVector<DeclRefExpr *, 32> InnerDeclRefs;127 128 SmallVector<DeclRefExpr *, 32> BlockDeclRefs;129 130 // Block related declarations.131 llvm::SmallSetVector<ValueDecl *, 8> BlockByCopyDecls;132 llvm::SmallSetVector<ValueDecl *, 8> BlockByRefDecls;133 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;134 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;135 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;136 137 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;138 139 // This maps an original source AST to it's rewritten form. This allows140 // us to avoid rewriting the same node twice (which is very uncommon).141 // This is needed to support some of the exotic property rewriting.142 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;143 144 // Needed for header files being rewritten145 bool IsHeader;146 bool SilenceRewriteMacroWarning;147 bool objc_impl_method;148 149 bool DisableReplaceStmt;150 class DisableReplaceStmtScope {151 RewriteObjC &R;152 bool SavedValue;153 154 public:155 DisableReplaceStmtScope(RewriteObjC &R)156 : R(R), SavedValue(R.DisableReplaceStmt) {157 R.DisableReplaceStmt = true;158 }159 160 ~DisableReplaceStmtScope() {161 R.DisableReplaceStmt = SavedValue;162 }163 };164 165 void InitializeCommon(ASTContext &context);166 167 public:168 // Top Level Driver code.169 bool HandleTopLevelDecl(DeclGroupRef D) override {170 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {171 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {172 if (!Class->isThisDeclarationADefinition()) {173 RewriteForwardClassDecl(D);174 break;175 }176 }177 178 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {179 if (!Proto->isThisDeclarationADefinition()) {180 RewriteForwardProtocolDecl(D);181 break;182 }183 }184 185 HandleTopLevelSingleDecl(*I);186 }187 return true;188 }189 190 void HandleTopLevelSingleDecl(Decl *D);191 void HandleDeclInMainFile(Decl *D);192 RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,193 DiagnosticsEngine &D, const LangOptions &LOpts,194 bool silenceMacroWarn);195 196 ~RewriteObjC() override {}197 198 void HandleTranslationUnit(ASTContext &C) override;199 200 void ReplaceStmt(Stmt *Old, Stmt *New) {201 ReplaceStmtWithRange(Old, New, Old->getSourceRange());202 }203 204 void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {205 assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");206 207 Stmt *ReplacingStmt = ReplacedNodes[Old];208 if (ReplacingStmt)209 return; // We can't rewrite the same node twice.210 211 if (DisableReplaceStmt)212 return;213 214 // Measure the old text.215 int Size = Rewrite.getRangeSize(SrcRange);216 if (Size == -1) {217 Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)218 << Old->getSourceRange();219 return;220 }221 // Get the new text.222 std::string Str;223 llvm::raw_string_ostream S(Str);224 New->printPretty(S, nullptr, PrintingPolicy(LangOpts));225 226 // If replacement succeeded or warning disabled return with no warning.227 if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {228 ReplacedNodes[Old] = New;229 return;230 }231 if (SilenceRewriteMacroWarning)232 return;233 Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)234 << Old->getSourceRange();235 }236 237 void InsertText(SourceLocation Loc, StringRef Str,238 bool InsertAfter = true) {239 // If insertion succeeded or warning disabled return with no warning.240 if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||241 SilenceRewriteMacroWarning)242 return;243 244 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);245 }246 247 void ReplaceText(SourceLocation Start, unsigned OrigLength,248 StringRef Str) {249 // If removal succeeded or warning disabled return with no warning.250 if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||251 SilenceRewriteMacroWarning)252 return;253 254 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);255 }256 257 // Syntactic Rewriting.258 void RewriteRecordBody(RecordDecl *RD);259 void RewriteInclude();260 void RewriteForwardClassDecl(DeclGroupRef D);261 void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);262 void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,263 const std::string &typedefString);264 void RewriteImplementations();265 void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,266 ObjCImplementationDecl *IMD,267 ObjCCategoryImplDecl *CID);268 void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);269 void RewriteImplementationDecl(Decl *Dcl);270 void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,271 ObjCMethodDecl *MDecl, std::string &ResultStr);272 void RewriteTypeIntoString(QualType T, std::string &ResultStr,273 const FunctionType *&FPRetType);274 void RewriteByRefString(std::string &ResultStr, const std::string &Name,275 ValueDecl *VD, bool def=false);276 void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);277 void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);278 void RewriteForwardProtocolDecl(DeclGroupRef D);279 void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);280 void RewriteMethodDeclaration(ObjCMethodDecl *Method);281 void RewriteProperty(ObjCPropertyDecl *prop);282 void RewriteFunctionDecl(FunctionDecl *FD);283 void RewriteBlockPointerType(std::string& Str, QualType Type);284 void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);285 void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);286 void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);287 void RewriteTypeOfDecl(VarDecl *VD);288 void RewriteObjCQualifiedInterfaceTypes(Expr *E);289 290 // Expression Rewriting.291 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);292 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);293 Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);294 Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);295 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);296 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);297 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);298 Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);299 void RewriteTryReturnStmts(Stmt *S);300 void RewriteSyncReturnStmts(Stmt *S, std::string buf);301 Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);302 Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);303 Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);304 Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,305 SourceLocation OrigEnd);306 Stmt *RewriteBreakStmt(BreakStmt *S);307 Stmt *RewriteContinueStmt(ContinueStmt *S);308 void RewriteCastExpr(CStyleCastExpr *CE);309 310 // Block rewriting.311 void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);312 313 // Block specific rewrite rules.314 void RewriteBlockPointerDecl(NamedDecl *VD);315 void RewriteByRefVar(VarDecl *VD);316 Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);317 Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);318 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);319 320 void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,321 std::string &Result);322 323 void Initialize(ASTContext &context) override = 0;324 325 // Metadata Rewriting.326 virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0;327 virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,328 StringRef prefix,329 StringRef ClassName,330 std::string &Result) = 0;331 virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,332 std::string &Result) = 0;333 virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,334 StringRef prefix,335 StringRef ClassName,336 std::string &Result) = 0;337 virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,338 std::string &Result) = 0;339 340 // Rewriting ivar access341 virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0;342 virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,343 std::string &Result) = 0;344 345 // Misc. AST transformation routines. Sometimes they end up calling346 // rewriting routines on the new ASTs.347 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,348 ArrayRef<Expr *> Args,349 SourceLocation StartLoc=SourceLocation(),350 SourceLocation EndLoc=SourceLocation());351 CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,352 QualType msgSendType,353 QualType returnType,354 SmallVectorImpl<QualType> &ArgTypes,355 SmallVectorImpl<Expr*> &MsgExprs,356 ObjCMethodDecl *Method);357 Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,358 SourceLocation StartLoc=SourceLocation(),359 SourceLocation EndLoc=SourceLocation());360 361 void SynthCountByEnumWithState(std::string &buf);362 void SynthMsgSendFunctionDecl();363 void SynthMsgSendSuperFunctionDecl();364 void SynthMsgSendStretFunctionDecl();365 void SynthMsgSendFpretFunctionDecl();366 void SynthMsgSendSuperStretFunctionDecl();367 void SynthGetClassFunctionDecl();368 void SynthGetMetaClassFunctionDecl();369 void SynthGetSuperClassFunctionDecl();370 void SynthSelGetUidFunctionDecl();371 void SynthSuperConstructorFunctionDecl();372 373 std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);374 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,375 StringRef funcName, std::string Tag);376 std::string SynthesizeBlockFunc(BlockExpr *CE, int i,377 StringRef funcName, std::string Tag);378 std::string SynthesizeBlockImpl(BlockExpr *CE,379 std::string Tag, std::string Desc);380 std::string SynthesizeBlockDescriptor(std::string DescTag,381 std::string ImplTag,382 int i, StringRef funcName,383 unsigned hasCopy);384 Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);385 void SynthesizeBlockLiterals(SourceLocation FunLocStart,386 StringRef FunName);387 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);388 Stmt *SynthBlockInitExpr(BlockExpr *Exp,389 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);390 391 // Misc. helper routines.392 QualType getProtocolType();393 void WarnAboutReturnGotoStmts(Stmt *S);394 void HasReturnStmts(Stmt *S, bool &hasReturns);395 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);396 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);397 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);398 399 bool IsDeclStmtInForeachHeader(DeclStmt *DS);400 void CollectBlockDeclRefInfo(BlockExpr *Exp);401 void GetBlockDeclRefExprs(Stmt *S);402 void GetInnerBlockDeclRefExprs(Stmt *S,403 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,404 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);405 406 // We avoid calling Type::isBlockPointerType(), since it operates on the407 // canonical type. We only care if the top-level type is a closure pointer.408 bool isTopLevelBlockPointerType(QualType T) {409 return isa<BlockPointerType>(T);410 }411 412 /// convertBlockPointerToFunctionPointer - Converts a block-pointer type413 /// to a function pointer type and upon success, returns true; false414 /// otherwise.415 bool convertBlockPointerToFunctionPointer(QualType &T) {416 if (isTopLevelBlockPointerType(T)) {417 const auto *BPT = T->castAs<BlockPointerType>();418 T = Context->getPointerType(BPT->getPointeeType());419 return true;420 }421 return false;422 }423 424 bool needToScanForQualifiers(QualType T);425 QualType getSuperStructType();426 QualType getConstantStringStructType();427 QualType convertFunctionTypeOfBlocks(const FunctionType *FT);428 bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);429 430 void convertToUnqualifiedObjCType(QualType &T) {431 if (T->isObjCQualifiedIdType())432 T = Context->getObjCIdType();433 else if (T->isObjCQualifiedClassType())434 T = Context->getObjCClassType();435 else if (T->isObjCObjectPointerType() &&436 T->getPointeeType()->isObjCQualifiedInterfaceType()) {437 if (const ObjCObjectPointerType * OBJPT =438 T->getAsObjCInterfacePointerType()) {439 const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();440 T = QualType(IFaceT, 0);441 T = Context->getPointerType(T);442 }443 }444 }445 446 // FIXME: This predicate seems like it would be useful to add to ASTContext.447 bool isObjCType(QualType T) {448 if (!LangOpts.ObjC)449 return false;450 451 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();452 453 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||454 OCT == Context->getCanonicalType(Context->getObjCClassType()))455 return true;456 457 if (const PointerType *PT = OCT->getAs<PointerType>()) {458 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||459 PT->getPointeeType()->isObjCQualifiedIdType())460 return true;461 }462 return false;463 }464 bool PointerTypeTakesAnyBlockArguments(QualType QT);465 bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);466 void GetExtentOfArgList(const char *Name, const char *&LParen,467 const char *&RParen);468 469 void QuoteDoublequotes(std::string &From, std::string &To) {470 for (unsigned i = 0; i < From.length(); i++) {471 if (From[i] == '"')472 To += "\\\"";473 else474 To += From[i];475 }476 }477 478 QualType getSimpleFunctionType(QualType result,479 ArrayRef<QualType> args,480 bool variadic = false) {481 if (result == Context->getObjCInstanceType())482 result = Context->getObjCIdType();483 FunctionProtoType::ExtProtoInfo fpi;484 fpi.Variadic = variadic;485 return Context->getFunctionType(result, args, fpi);486 }487 488 // Helper function: create a CStyleCastExpr with trivial type source info.489 CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,490 CastKind Kind, Expr *E) {491 TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());492 return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,493 FPOptionsOverride(), TInfo,494 SourceLocation(), SourceLocation());495 }496 497 StringLiteral *getStringLiteral(StringRef Str) {498 QualType StrType = Context->getConstantArrayType(499 Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,500 ArraySizeModifier::Normal, 0);501 return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,502 /*Pascal=*/false, StrType, SourceLocation());503 }504 };505 506 class RewriteObjCFragileABI : public RewriteObjC {507 public:508 RewriteObjCFragileABI(std::string inFile, std::unique_ptr<raw_ostream> OS,509 DiagnosticsEngine &D, const LangOptions &LOpts,510 bool silenceMacroWarn)511 : RewriteObjC(inFile, std::move(OS), D, LOpts, silenceMacroWarn) {}512 513 ~RewriteObjCFragileABI() override {}514 void Initialize(ASTContext &context) override;515 516 // Rewriting metadata517 template<typename MethodIterator>518 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,519 MethodIterator MethodEnd,520 bool IsInstanceMethod,521 StringRef prefix,522 StringRef ClassName,523 std::string &Result);524 void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,525 StringRef prefix, StringRef ClassName,526 std::string &Result) override;527 void RewriteObjCProtocolListMetaData(528 const ObjCList<ObjCProtocolDecl> &Prots,529 StringRef prefix, StringRef ClassName, std::string &Result) override;530 void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,531 std::string &Result) override;532 void RewriteMetaDataIntoBuffer(std::string &Result) override;533 void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,534 std::string &Result) override;535 536 // Rewriting ivar537 void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,538 std::string &Result) override;539 Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) override;540 };541} // end anonymous namespace542 543void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,544 NamedDecl *D) {545 if (const FunctionProtoType *fproto546 = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {547 for (const auto &I : fproto->param_types())548 if (isTopLevelBlockPointerType(I)) {549 // All the args are checked/rewritten. Don't call twice!550 RewriteBlockPointerDecl(D);551 break;552 }553 }554}555 556void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {557 const PointerType *PT = funcType->getAs<PointerType>();558 if (PT && PointerTypeTakesAnyBlockArguments(funcType))559 RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);560}561 562static bool IsHeaderFile(const std::string &Filename) {563 std::string::size_type DotPos = Filename.rfind('.');564 565 if (DotPos == std::string::npos) {566 // no file extension567 return false;568 }569 570 std::string Ext = Filename.substr(DotPos + 1);571 // C header: .h572 // C++ header: .hh or .H;573 return Ext == "h" || Ext == "hh" || Ext == "H";574}575 576RewriteObjC::RewriteObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,577 DiagnosticsEngine &D, const LangOptions &LOpts,578 bool silenceMacroWarn)579 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),580 SilenceRewriteMacroWarning(silenceMacroWarn) {581 IsHeader = IsHeaderFile(inFile);582 RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,583 "rewriting sub-expression within a macro (may not be correct)");584 TryFinallyContainsReturnDiag = Diags.getCustomDiagID(585 DiagnosticsEngine::Warning,586 "rewriter doesn't support user-specified control flow semantics "587 "for @try/@finally (code may not execute properly)");588}589 590std::unique_ptr<ASTConsumer>591clang::CreateObjCRewriter(const std::string &InFile,592 std::unique_ptr<raw_ostream> OS,593 DiagnosticsEngine &Diags, const LangOptions &LOpts,594 bool SilenceRewriteMacroWarning) {595 return std::make_unique<RewriteObjCFragileABI>(596 InFile, std::move(OS), Diags, LOpts, SilenceRewriteMacroWarning);597}598 599void RewriteObjC::InitializeCommon(ASTContext &context) {600 Context = &context;601 SM = &Context->getSourceManager();602 TUDecl = Context->getTranslationUnitDecl();603 MsgSendFunctionDecl = nullptr;604 MsgSendSuperFunctionDecl = nullptr;605 MsgSendStretFunctionDecl = nullptr;606 MsgSendSuperStretFunctionDecl = nullptr;607 MsgSendFpretFunctionDecl = nullptr;608 GetClassFunctionDecl = nullptr;609 GetMetaClassFunctionDecl = nullptr;610 GetSuperClassFunctionDecl = nullptr;611 SelGetUidFunctionDecl = nullptr;612 CFStringFunctionDecl = nullptr;613 ConstantStringClassReference = nullptr;614 NSStringRecord = nullptr;615 CurMethodDef = nullptr;616 CurFunctionDef = nullptr;617 CurFunctionDeclToDeclareForBlock = nullptr;618 GlobalVarDecl = nullptr;619 SuperStructDecl = nullptr;620 ProtocolTypeDecl = nullptr;621 ConstantStringDecl = nullptr;622 BcLabelCount = 0;623 SuperConstructorFunctionDecl = nullptr;624 NumObjCStringLiterals = 0;625 PropParentMap = nullptr;626 CurrentBody = nullptr;627 DisableReplaceStmt = false;628 objc_impl_method = false;629 630 // Get the ID and start/end of the main file.631 MainFileID = SM->getMainFileID();632 llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);633 MainFileStart = MainBuf.getBufferStart();634 MainFileEnd = MainBuf.getBufferEnd();635 636 Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());637}638 639//===----------------------------------------------------------------------===//640// Top Level Driver Code641//===----------------------------------------------------------------------===//642 643void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {644 if (Diags.hasErrorOccurred())645 return;646 647 // Two cases: either the decl could be in the main file, or it could be in a648 // #included file. If the former, rewrite it now. If the later, check to see649 // if we rewrote the #include/#import.650 SourceLocation Loc = D->getLocation();651 Loc = SM->getExpansionLoc(Loc);652 653 // If this is for a builtin, ignore it.654 if (Loc.isInvalid()) return;655 656 // Look for built-in declarations that we need to refer during the rewrite.657 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {658 RewriteFunctionDecl(FD);659 } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {660 // declared in <Foundation/NSString.h>661 if (FVD->getName() == "_NSConstantStringClassReference") {662 ConstantStringClassReference = FVD;663 return;664 }665 } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) {666 if (ID->isThisDeclarationADefinition())667 RewriteInterfaceDecl(ID);668 } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {669 RewriteCategoryDecl(CD);670 } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {671 if (PD->isThisDeclarationADefinition())672 RewriteProtocolDecl(PD);673 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {674 // Recurse into linkage specifications675 for (DeclContext::decl_iterator DI = LSD->decls_begin(),676 DIEnd = LSD->decls_end();677 DI != DIEnd; ) {678 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {679 if (!IFace->isThisDeclarationADefinition()) {680 SmallVector<Decl *, 8> DG;681 SourceLocation StartLoc = IFace->getBeginLoc();682 do {683 if (isa<ObjCInterfaceDecl>(*DI) &&684 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&685 StartLoc == (*DI)->getBeginLoc())686 DG.push_back(*DI);687 else688 break;689 690 ++DI;691 } while (DI != DIEnd);692 RewriteForwardClassDecl(DG);693 continue;694 }695 }696 697 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {698 if (!Proto->isThisDeclarationADefinition()) {699 SmallVector<Decl *, 8> DG;700 SourceLocation StartLoc = Proto->getBeginLoc();701 do {702 if (isa<ObjCProtocolDecl>(*DI) &&703 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&704 StartLoc == (*DI)->getBeginLoc())705 DG.push_back(*DI);706 else707 break;708 709 ++DI;710 } while (DI != DIEnd);711 RewriteForwardProtocolDecl(DG);712 continue;713 }714 }715 716 HandleTopLevelSingleDecl(*DI);717 ++DI;718 }719 }720 // If we have a decl in the main file, see if we should rewrite it.721 if (SM->isWrittenInMainFile(Loc))722 return HandleDeclInMainFile(D);723}724 725//===----------------------------------------------------------------------===//726// Syntactic (non-AST) Rewriting Code727//===----------------------------------------------------------------------===//728 729void RewriteObjC::RewriteInclude() {730 SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);731 StringRef MainBuf = SM->getBufferData(MainFileID);732 const char *MainBufStart = MainBuf.begin();733 const char *MainBufEnd = MainBuf.end();734 size_t ImportLen = strlen("import");735 736 // Loop over the whole file, looking for includes.737 for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {738 if (*BufPtr == '#') {739 if (++BufPtr == MainBufEnd)740 return;741 while (*BufPtr == ' ' || *BufPtr == '\t')742 if (++BufPtr == MainBufEnd)743 return;744 if (!strncmp(BufPtr, "import", ImportLen)) {745 // replace import with include746 SourceLocation ImportLoc =747 LocStart.getLocWithOffset(BufPtr-MainBufStart);748 ReplaceText(ImportLoc, ImportLen, "include");749 BufPtr += ImportLen;750 }751 }752 }753}754 755static std::string getIvarAccessString(ObjCIvarDecl *OID) {756 const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface();757 std::string S;758 S = "((struct ";759 S += ClassDecl->getIdentifier()->getName();760 S += "_IMPL *)self)->";761 S += OID->getName();762 return S;763}764 765void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,766 ObjCImplementationDecl *IMD,767 ObjCCategoryImplDecl *CID) {768 static bool objcGetPropertyDefined = false;769 static bool objcSetPropertyDefined = false;770 SourceLocation startLoc = PID->getBeginLoc();771 InsertText(startLoc, "// ");772 const char *startBuf = SM->getCharacterData(startLoc);773 assert((*startBuf == '@') && "bogus @synthesize location");774 const char *semiBuf = strchr(startBuf, ';');775 assert((*semiBuf == ';') && "@synthesize: can't find ';'");776 SourceLocation onePastSemiLoc =777 startLoc.getLocWithOffset(semiBuf-startBuf+1);778 779 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)780 return; // FIXME: is this correct?781 782 // Generate the 'getter' function.783 ObjCPropertyDecl *PD = PID->getPropertyDecl();784 ObjCIvarDecl *OID = PID->getPropertyIvarDecl();785 786 if (!OID)787 return;788 789 unsigned Attributes = PD->getPropertyAttributes();790 if (PID->getGetterMethodDecl() && !PID->getGetterMethodDecl()->isDefined()) {791 bool GenGetProperty =792 !(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&793 (Attributes & (ObjCPropertyAttribute::kind_retain |794 ObjCPropertyAttribute::kind_copy));795 std::string Getr;796 if (GenGetProperty && !objcGetPropertyDefined) {797 objcGetPropertyDefined = true;798 // FIXME. Is this attribute correct in all cases?799 Getr = "\nextern \"C\" __declspec(dllimport) "800 "id objc_getProperty(id, SEL, long, bool);\n";801 }802 RewriteObjCMethodDecl(OID->getContainingInterface(),803 PID->getGetterMethodDecl(), Getr);804 Getr += "{ ";805 // Synthesize an explicit cast to gain access to the ivar.806 // See objc-act.c:objc_synthesize_new_getter() for details.807 if (GenGetProperty) {808 // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)809 Getr += "typedef ";810 const FunctionType *FPRetType = nullptr;811 RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,812 FPRetType);813 Getr += " _TYPE";814 if (FPRetType) {815 Getr += ")"; // close the precedence "scope" for "*".816 817 // Now, emit the argument types (if any).818 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){819 Getr += "(";820 for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {821 if (i) Getr += ", ";822 std::string ParamStr =823 FT->getParamType(i).getAsString(Context->getPrintingPolicy());824 Getr += ParamStr;825 }826 if (FT->isVariadic()) {827 if (FT->getNumParams())828 Getr += ", ";829 Getr += "...";830 }831 Getr += ")";832 } else833 Getr += "()";834 }835 Getr += ";\n";836 Getr += "return (_TYPE)";837 Getr += "objc_getProperty(self, _cmd, ";838 RewriteIvarOffsetComputation(OID, Getr);839 Getr += ", 1)";840 }841 else842 Getr += "return " + getIvarAccessString(OID);843 Getr += "; }";844 InsertText(onePastSemiLoc, Getr);845 }846 847 if (PD->isReadOnly() || !PID->getSetterMethodDecl() ||848 PID->getSetterMethodDecl()->isDefined())849 return;850 851 // Generate the 'setter' function.852 std::string Setr;853 bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |854 ObjCPropertyAttribute::kind_copy);855 if (GenSetProperty && !objcSetPropertyDefined) {856 objcSetPropertyDefined = true;857 // FIXME. Is this attribute correct in all cases?858 Setr = "\nextern \"C\" __declspec(dllimport) "859 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";860 }861 862 RewriteObjCMethodDecl(OID->getContainingInterface(),863 PID->getSetterMethodDecl(), Setr);864 Setr += "{ ";865 // Synthesize an explicit cast to initialize the ivar.866 // See objc-act.c:objc_synthesize_new_setter() for details.867 if (GenSetProperty) {868 Setr += "objc_setProperty (self, _cmd, ";869 RewriteIvarOffsetComputation(OID, Setr);870 Setr += ", (id)";871 Setr += PD->getName();872 Setr += ", ";873 if (Attributes & ObjCPropertyAttribute::kind_nonatomic)874 Setr += "0, ";875 else876 Setr += "1, ";877 if (Attributes & ObjCPropertyAttribute::kind_copy)878 Setr += "1)";879 else880 Setr += "0)";881 }882 else {883 Setr += getIvarAccessString(OID) + " = ";884 Setr += PD->getName();885 }886 Setr += "; }";887 InsertText(onePastSemiLoc, Setr);888}889 890static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,891 std::string &typedefString) {892 typedefString += "#ifndef _REWRITER_typedef_";893 typedefString += ForwardDecl->getNameAsString();894 typedefString += "\n";895 typedefString += "#define _REWRITER_typedef_";896 typedefString += ForwardDecl->getNameAsString();897 typedefString += "\n";898 typedefString += "typedef struct objc_object ";899 typedefString += ForwardDecl->getNameAsString();900 typedefString += ";\n#endif\n";901}902 903void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,904 const std::string &typedefString) {905 SourceLocation startLoc = ClassDecl->getBeginLoc();906 const char *startBuf = SM->getCharacterData(startLoc);907 const char *semiPtr = strchr(startBuf, ';');908 // Replace the @class with typedefs corresponding to the classes.909 ReplaceText(startLoc, semiPtr - startBuf + 1, typedefString);910}911 912void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) {913 std::string typedefString;914 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {915 ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I);916 if (I == D.begin()) {917 // Translate to typedef's that forward reference structs with the same name918 // as the class. As a convenience, we include the original declaration919 // as a comment.920 typedefString += "// @class ";921 typedefString += ForwardDecl->getNameAsString();922 typedefString += ";\n";923 }924 RewriteOneForwardClassDecl(ForwardDecl, typedefString);925 }926 DeclGroupRef::iterator I = D.begin();927 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);928}929 930void RewriteObjC::RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &D) {931 std::string typedefString;932 for (unsigned i = 0; i < D.size(); i++) {933 ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);934 if (i == 0) {935 typedefString += "// @class ";936 typedefString += ForwardDecl->getNameAsString();937 typedefString += ";\n";938 }939 RewriteOneForwardClassDecl(ForwardDecl, typedefString);940 }941 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);942}943 944void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {945 // When method is a synthesized one, such as a getter/setter there is946 // nothing to rewrite.947 if (Method->isImplicit())948 return;949 SourceLocation LocStart = Method->getBeginLoc();950 SourceLocation LocEnd = Method->getEndLoc();951 952 if (SM->getExpansionLineNumber(LocEnd) >953 SM->getExpansionLineNumber(LocStart)) {954 InsertText(LocStart, "#if 0\n");955 ReplaceText(LocEnd, 1, ";\n#endif\n");956 } else {957 InsertText(LocStart, "// ");958 }959}960 961void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {962 SourceLocation Loc = prop->getAtLoc();963 964 ReplaceText(Loc, 0, "// ");965 // FIXME: handle properties that are declared across multiple lines.966}967 968void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {969 SourceLocation LocStart = CatDecl->getBeginLoc();970 971 // FIXME: handle category headers that are declared across multiple lines.972 ReplaceText(LocStart, 0, "// ");973 974 for (auto *I : CatDecl->instance_properties())975 RewriteProperty(I);976 for (auto *I : CatDecl->instance_methods())977 RewriteMethodDeclaration(I);978 for (auto *I : CatDecl->class_methods())979 RewriteMethodDeclaration(I);980 981 // Lastly, comment out the @end.982 ReplaceText(CatDecl->getAtEndRange().getBegin(),983 strlen("@end"), "/* @end */");984}985 986void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {987 SourceLocation LocStart = PDecl->getBeginLoc();988 assert(PDecl->isThisDeclarationADefinition());989 990 // FIXME: handle protocol headers that are declared across multiple lines.991 ReplaceText(LocStart, 0, "// ");992 993 for (auto *I : PDecl->instance_methods())994 RewriteMethodDeclaration(I);995 for (auto *I : PDecl->class_methods())996 RewriteMethodDeclaration(I);997 for (auto *I : PDecl->instance_properties())998 RewriteProperty(I);999 1000 // Lastly, comment out the @end.1001 SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();1002 ReplaceText(LocEnd, strlen("@end"), "/* @end */");1003 1004 // Must comment out @optional/@required1005 const char *startBuf = SM->getCharacterData(LocStart);1006 const char *endBuf = SM->getCharacterData(LocEnd);1007 for (const char *p = startBuf; p < endBuf; p++) {1008 if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {1009 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1010 ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");1011 1012 }1013 else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {1014 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1015 ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");1016 1017 }1018 }1019}1020 1021void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {1022 SourceLocation LocStart = (*D.begin())->getBeginLoc();1023 if (LocStart.isInvalid())1024 llvm_unreachable("Invalid SourceLocation");1025 // FIXME: handle forward protocol that are declared across multiple lines.1026 ReplaceText(LocStart, 0, "// ");1027}1028 1029void1030RewriteObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {1031 SourceLocation LocStart = DG[0]->getBeginLoc();1032 if (LocStart.isInvalid())1033 llvm_unreachable("Invalid SourceLocation");1034 // FIXME: handle forward protocol that are declared across multiple lines.1035 ReplaceText(LocStart, 0, "// ");1036}1037 1038void RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,1039 const FunctionType *&FPRetType) {1040 if (T->isObjCQualifiedIdType())1041 ResultStr += "id";1042 else if (T->isFunctionPointerType() ||1043 T->isBlockPointerType()) {1044 // needs special handling, since pointer-to-functions have special1045 // syntax (where a decaration models use).1046 QualType retType = T;1047 QualType PointeeTy;1048 if (const PointerType* PT = retType->getAs<PointerType>())1049 PointeeTy = PT->getPointeeType();1050 else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())1051 PointeeTy = BPT->getPointeeType();1052 if ((FPRetType = PointeeTy->getAs<FunctionType>())) {1053 ResultStr +=1054 FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());1055 ResultStr += "(*";1056 }1057 } else1058 ResultStr += T.getAsString(Context->getPrintingPolicy());1059}1060 1061void RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,1062 ObjCMethodDecl *OMD,1063 std::string &ResultStr) {1064 //fprintf(stderr,"In RewriteObjCMethodDecl\n");1065 const FunctionType *FPRetType = nullptr;1066 ResultStr += "\nstatic ";1067 RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);1068 ResultStr += " ";1069 1070 // Unique method name1071 std::string NameStr;1072 1073 if (OMD->isInstanceMethod())1074 NameStr += "_I_";1075 else1076 NameStr += "_C_";1077 1078 NameStr += IDecl->getNameAsString();1079 NameStr += "_";1080 1081 if (ObjCCategoryImplDecl *CID =1082 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {1083 NameStr += CID->getNameAsString();1084 NameStr += "_";1085 }1086 // Append selector names, replacing ':' with '_'1087 {1088 std::string selString = OMD->getSelector().getAsString();1089 int len = selString.size();1090 for (int i = 0; i < len; i++)1091 if (selString[i] == ':')1092 selString[i] = '_';1093 NameStr += selString;1094 }1095 // Remember this name for metadata emission1096 MethodInternalNames[OMD] = NameStr;1097 ResultStr += NameStr;1098 1099 // Rewrite arguments1100 ResultStr += "(";1101 1102 // invisible arguments1103 if (OMD->isInstanceMethod()) {1104 QualType selfTy = Context->getObjCInterfaceType(IDecl);1105 selfTy = Context->getPointerType(selfTy);1106 if (!LangOpts.MicrosoftExt) {1107 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))1108 ResultStr += "struct ";1109 }1110 // When rewriting for Microsoft, explicitly omit the structure name.1111 ResultStr += IDecl->getNameAsString();1112 ResultStr += " *";1113 }1114 else1115 ResultStr += Context->getObjCClassType().getAsString(1116 Context->getPrintingPolicy());1117 1118 ResultStr += " self, ";1119 ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());1120 ResultStr += " _cmd";1121 1122 // Method arguments.1123 for (const auto *PDecl : OMD->parameters()) {1124 ResultStr += ", ";1125 if (PDecl->getType()->isObjCQualifiedIdType()) {1126 ResultStr += "id ";1127 ResultStr += PDecl->getNameAsString();1128 } else {1129 std::string Name = PDecl->getNameAsString();1130 QualType QT = PDecl->getType();1131 // Make sure we convert "t (^)(...)" to "t (*)(...)".1132 (void)convertBlockPointerToFunctionPointer(QT);1133 QT.getAsStringInternal(Name, Context->getPrintingPolicy());1134 ResultStr += Name;1135 }1136 }1137 if (OMD->isVariadic())1138 ResultStr += ", ...";1139 ResultStr += ") ";1140 1141 if (FPRetType) {1142 ResultStr += ")"; // close the precedence "scope" for "*".1143 1144 // Now, emit the argument types (if any).1145 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {1146 ResultStr += "(";1147 for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {1148 if (i) ResultStr += ", ";1149 std::string ParamStr =1150 FT->getParamType(i).getAsString(Context->getPrintingPolicy());1151 ResultStr += ParamStr;1152 }1153 if (FT->isVariadic()) {1154 if (FT->getNumParams())1155 ResultStr += ", ";1156 ResultStr += "...";1157 }1158 ResultStr += ")";1159 } else {1160 ResultStr += "()";1161 }1162 }1163}1164 1165void RewriteObjC::RewriteImplementationDecl(Decl *OID) {1166 ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);1167 ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);1168 assert((IMD || CID) && "Unknown ImplementationDecl");1169 1170 InsertText(IMD ? IMD->getBeginLoc() : CID->getBeginLoc(), "// ");1171 1172 for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {1173 if (!OMD->getBody())1174 continue;1175 std::string ResultStr;1176 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1177 SourceLocation LocStart = OMD->getBeginLoc();1178 SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();1179 1180 const char *startBuf = SM->getCharacterData(LocStart);1181 const char *endBuf = SM->getCharacterData(LocEnd);1182 ReplaceText(LocStart, endBuf-startBuf, ResultStr);1183 }1184 1185 for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {1186 if (!OMD->getBody())1187 continue;1188 std::string ResultStr;1189 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1190 SourceLocation LocStart = OMD->getBeginLoc();1191 SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();1192 1193 const char *startBuf = SM->getCharacterData(LocStart);1194 const char *endBuf = SM->getCharacterData(LocEnd);1195 ReplaceText(LocStart, endBuf-startBuf, ResultStr);1196 }1197 for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())1198 RewritePropertyImplDecl(I, IMD, CID);1199 1200 InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");1201}1202 1203void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {1204 std::string ResultStr;1205 if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) {1206 // we haven't seen a forward decl - generate a typedef.1207 ResultStr = "#ifndef _REWRITER_typedef_";1208 ResultStr += ClassDecl->getNameAsString();1209 ResultStr += "\n";1210 ResultStr += "#define _REWRITER_typedef_";1211 ResultStr += ClassDecl->getNameAsString();1212 ResultStr += "\n";1213 ResultStr += "typedef struct objc_object ";1214 ResultStr += ClassDecl->getNameAsString();1215 ResultStr += ";\n#endif\n";1216 // Mark this typedef as having been generated.1217 ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl());1218 }1219 RewriteObjCInternalStruct(ClassDecl, ResultStr);1220 1221 for (auto *I : ClassDecl->instance_properties())1222 RewriteProperty(I);1223 for (auto *I : ClassDecl->instance_methods())1224 RewriteMethodDeclaration(I);1225 for (auto *I : ClassDecl->class_methods())1226 RewriteMethodDeclaration(I);1227 1228 // Lastly, comment out the @end.1229 ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),1230 "/* @end */");1231}1232 1233Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {1234 SourceRange OldRange = PseudoOp->getSourceRange();1235 1236 // We just magically know some things about the structure of this1237 // expression.1238 ObjCMessageExpr *OldMsg =1239 cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(1240 PseudoOp->getNumSemanticExprs() - 1));1241 1242 // Because the rewriter doesn't allow us to rewrite rewritten code,1243 // we need to suppress rewriting the sub-statements.1244 Expr *Base, *RHS;1245 {1246 DisableReplaceStmtScope S(*this);1247 1248 // Rebuild the base expression if we have one.1249 Base = nullptr;1250 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1251 Base = OldMsg->getInstanceReceiver();1252 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1253 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1254 }1255 1256 // Rebuild the RHS.1257 RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS();1258 RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr();1259 RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS));1260 }1261 1262 // TODO: avoid this copy.1263 SmallVector<SourceLocation, 1> SelLocs;1264 OldMsg->getSelectorLocs(SelLocs);1265 1266 ObjCMessageExpr *NewMsg = nullptr;1267 switch (OldMsg->getReceiverKind()) {1268 case ObjCMessageExpr::Class:1269 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1270 OldMsg->getValueKind(),1271 OldMsg->getLeftLoc(),1272 OldMsg->getClassReceiverTypeInfo(),1273 OldMsg->getSelector(),1274 SelLocs,1275 OldMsg->getMethodDecl(),1276 RHS,1277 OldMsg->getRightLoc(),1278 OldMsg->isImplicit());1279 break;1280 1281 case ObjCMessageExpr::Instance:1282 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1283 OldMsg->getValueKind(),1284 OldMsg->getLeftLoc(),1285 Base,1286 OldMsg->getSelector(),1287 SelLocs,1288 OldMsg->getMethodDecl(),1289 RHS,1290 OldMsg->getRightLoc(),1291 OldMsg->isImplicit());1292 break;1293 1294 case ObjCMessageExpr::SuperClass:1295 case ObjCMessageExpr::SuperInstance:1296 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1297 OldMsg->getValueKind(),1298 OldMsg->getLeftLoc(),1299 OldMsg->getSuperLoc(),1300 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1301 OldMsg->getSuperType(),1302 OldMsg->getSelector(),1303 SelLocs,1304 OldMsg->getMethodDecl(),1305 RHS,1306 OldMsg->getRightLoc(),1307 OldMsg->isImplicit());1308 break;1309 }1310 1311 Stmt *Replacement = SynthMessageExpr(NewMsg);1312 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1313 return Replacement;1314}1315 1316Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {1317 SourceRange OldRange = PseudoOp->getSourceRange();1318 1319 // We just magically know some things about the structure of this1320 // expression.1321 ObjCMessageExpr *OldMsg =1322 cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());1323 1324 // Because the rewriter doesn't allow us to rewrite rewritten code,1325 // we need to suppress rewriting the sub-statements.1326 Expr *Base = nullptr;1327 {1328 DisableReplaceStmtScope S(*this);1329 1330 // Rebuild the base expression if we have one.1331 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1332 Base = OldMsg->getInstanceReceiver();1333 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1334 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1335 }1336 }1337 1338 // Intentionally empty.1339 SmallVector<SourceLocation, 1> SelLocs;1340 SmallVector<Expr*, 1> Args;1341 1342 ObjCMessageExpr *NewMsg = nullptr;1343 switch (OldMsg->getReceiverKind()) {1344 case ObjCMessageExpr::Class:1345 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1346 OldMsg->getValueKind(),1347 OldMsg->getLeftLoc(),1348 OldMsg->getClassReceiverTypeInfo(),1349 OldMsg->getSelector(),1350 SelLocs,1351 OldMsg->getMethodDecl(),1352 Args,1353 OldMsg->getRightLoc(),1354 OldMsg->isImplicit());1355 break;1356 1357 case ObjCMessageExpr::Instance:1358 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1359 OldMsg->getValueKind(),1360 OldMsg->getLeftLoc(),1361 Base,1362 OldMsg->getSelector(),1363 SelLocs,1364 OldMsg->getMethodDecl(),1365 Args,1366 OldMsg->getRightLoc(),1367 OldMsg->isImplicit());1368 break;1369 1370 case ObjCMessageExpr::SuperClass:1371 case ObjCMessageExpr::SuperInstance:1372 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1373 OldMsg->getValueKind(),1374 OldMsg->getLeftLoc(),1375 OldMsg->getSuperLoc(),1376 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1377 OldMsg->getSuperType(),1378 OldMsg->getSelector(),1379 SelLocs,1380 OldMsg->getMethodDecl(),1381 Args,1382 OldMsg->getRightLoc(),1383 OldMsg->isImplicit());1384 break;1385 }1386 1387 Stmt *Replacement = SynthMessageExpr(NewMsg);1388 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1389 return Replacement;1390}1391 1392/// SynthCountByEnumWithState - To print:1393/// ((unsigned int (*)1394/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))1395/// (void *)objc_msgSend)((id)l_collection,1396/// sel_registerName(1397/// "countByEnumeratingWithState:objects:count:"),1398/// &enumState,1399/// (id *)__rw_items, (unsigned int)16)1400///1401void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {1402 buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "1403 "id *, unsigned int))(void *)objc_msgSend)";1404 buf += "\n\t\t";1405 buf += "((id)l_collection,\n\t\t";1406 buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";1407 buf += "\n\t\t";1408 buf += "&enumState, "1409 "(id *)__rw_items, (unsigned int)16)";1410}1411 1412/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach1413/// statement to exit to its outer synthesized loop.1414///1415Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {1416 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1417 return S;1418 // replace break with goto __break_label1419 std::string buf;1420 1421 SourceLocation startLoc = S->getBeginLoc();1422 buf = "goto __break_label_";1423 buf += utostr(ObjCBcLabelNo.back());1424 ReplaceText(startLoc, strlen("break"), buf);1425 1426 return nullptr;1427}1428 1429/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach1430/// statement to continue with its inner synthesized loop.1431///1432Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {1433 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1434 return S;1435 // replace continue with goto __continue_label1436 std::string buf;1437 1438 SourceLocation startLoc = S->getBeginLoc();1439 buf = "goto __continue_label_";1440 buf += utostr(ObjCBcLabelNo.back());1441 ReplaceText(startLoc, strlen("continue"), buf);1442 1443 return nullptr;1444}1445 1446/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.1447/// It rewrites:1448/// for ( type elem in collection) { stmts; }1449 1450/// Into:1451/// {1452/// type elem;1453/// struct __objcFastEnumerationState enumState = { 0 };1454/// id __rw_items[16];1455/// id l_collection = (id)collection;1456/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState1457/// objects:__rw_items count:16];1458/// if (limit) {1459/// unsigned long startMutations = *enumState.mutationsPtr;1460/// do {1461/// unsigned long counter = 0;1462/// do {1463/// if (startMutations != *enumState.mutationsPtr)1464/// objc_enumerationMutation(l_collection);1465/// elem = (type)enumState.itemsPtr[counter++];1466/// stmts;1467/// __continue_label: ;1468/// } while (counter < limit);1469/// } while (limit = [l_collection countByEnumeratingWithState:&enumState1470/// objects:__rw_items count:16]);1471/// elem = nil;1472/// __break_label: ;1473/// }1474/// else1475/// elem = nil;1476/// }1477///1478Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,1479 SourceLocation OrigEnd) {1480 assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");1481 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&1482 "ObjCForCollectionStmt Statement stack mismatch");1483 assert(!ObjCBcLabelNo.empty() &&1484 "ObjCForCollectionStmt - Label No stack empty");1485 1486 SourceLocation startLoc = S->getBeginLoc();1487 const char *startBuf = SM->getCharacterData(startLoc);1488 StringRef elementName;1489 std::string elementTypeAsString;1490 std::string buf;1491 buf = "\n{\n\t";1492 if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {1493 // type elem;1494 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());1495 QualType ElementType = cast<ValueDecl>(D)->getType();1496 if (ElementType->isObjCQualifiedIdType() ||1497 ElementType->isObjCQualifiedInterfaceType())1498 // Simply use 'id' for all qualified types.1499 elementTypeAsString = "id";1500 else1501 elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());1502 buf += elementTypeAsString;1503 buf += " ";1504 elementName = D->getName();1505 buf += elementName;1506 buf += ";\n\t";1507 }1508 else {1509 DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());1510 elementName = DR->getDecl()->getName();1511 ValueDecl *VD = DR->getDecl();1512 if (VD->getType()->isObjCQualifiedIdType() ||1513 VD->getType()->isObjCQualifiedInterfaceType())1514 // Simply use 'id' for all qualified types.1515 elementTypeAsString = "id";1516 else1517 elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());1518 }1519 1520 // struct __objcFastEnumerationState enumState = { 0 };1521 buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";1522 // id __rw_items[16];1523 buf += "id __rw_items[16];\n\t";1524 // id l_collection = (id)1525 buf += "id l_collection = (id)";1526 // Find start location of 'collection' the hard way!1527 const char *startCollectionBuf = startBuf;1528 startCollectionBuf += 3; // skip 'for'1529 startCollectionBuf = strchr(startCollectionBuf, '(');1530 startCollectionBuf++; // skip '('1531 // find 'in' and skip it.1532 while (*startCollectionBuf != ' ' ||1533 *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||1534 (*(startCollectionBuf+3) != ' ' &&1535 *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))1536 startCollectionBuf++;1537 startCollectionBuf += 3;1538 1539 // Replace: "for (type element in" with string constructed thus far.1540 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);1541 // Replace ')' in for '(' type elem in collection ')' with ';'1542 SourceLocation rightParenLoc = S->getRParenLoc();1543 const char *rparenBuf = SM->getCharacterData(rightParenLoc);1544 SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);1545 buf = ";\n\t";1546 1547 // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState1548 // objects:__rw_items count:16];1549 // which is synthesized into:1550 // unsigned int limit =1551 // ((unsigned int (*)1552 // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))1553 // (void *)objc_msgSend)((id)l_collection,1554 // sel_registerName(1555 // "countByEnumeratingWithState:objects:count:"),1556 // (struct __objcFastEnumerationState *)&state,1557 // (id *)__rw_items, (unsigned int)16);1558 buf += "unsigned long limit =\n\t\t";1559 SynthCountByEnumWithState(buf);1560 buf += ";\n\t";1561 /// if (limit) {1562 /// unsigned long startMutations = *enumState.mutationsPtr;1563 /// do {1564 /// unsigned long counter = 0;1565 /// do {1566 /// if (startMutations != *enumState.mutationsPtr)1567 /// objc_enumerationMutation(l_collection);1568 /// elem = (type)enumState.itemsPtr[counter++];1569 buf += "if (limit) {\n\t";1570 buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";1571 buf += "do {\n\t\t";1572 buf += "unsigned long counter = 0;\n\t\t";1573 buf += "do {\n\t\t\t";1574 buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";1575 buf += "objc_enumerationMutation(l_collection);\n\t\t\t";1576 buf += elementName;1577 buf += " = (";1578 buf += elementTypeAsString;1579 buf += ")enumState.itemsPtr[counter++];";1580 // Replace ')' in for '(' type elem in collection ')' with all of these.1581 ReplaceText(lparenLoc, 1, buf);1582 1583 /// __continue_label: ;1584 /// } while (counter < limit);1585 /// } while (limit = [l_collection countByEnumeratingWithState:&enumState1586 /// objects:__rw_items count:16]);1587 /// elem = nil;1588 /// __break_label: ;1589 /// }1590 /// else1591 /// elem = nil;1592 /// }1593 ///1594 buf = ";\n\t";1595 buf += "__continue_label_";1596 buf += utostr(ObjCBcLabelNo.back());1597 buf += ": ;";1598 buf += "\n\t\t";1599 buf += "} while (counter < limit);\n\t";1600 buf += "} while (limit = ";1601 SynthCountByEnumWithState(buf);1602 buf += ");\n\t";1603 buf += elementName;1604 buf += " = ((";1605 buf += elementTypeAsString;1606 buf += ")0);\n\t";1607 buf += "__break_label_";1608 buf += utostr(ObjCBcLabelNo.back());1609 buf += ": ;\n\t";1610 buf += "}\n\t";1611 buf += "else\n\t\t";1612 buf += elementName;1613 buf += " = ((";1614 buf += elementTypeAsString;1615 buf += ")0);\n\t";1616 buf += "}\n";1617 1618 // Insert all these *after* the statement body.1619 // FIXME: If this should support Obj-C++, support CXXTryStmt1620 if (isa<CompoundStmt>(S->getBody())) {1621 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);1622 InsertText(endBodyLoc, buf);1623 } else {1624 /* Need to treat single statements specially. For example:1625 *1626 * for (A *a in b) if (stuff()) break;1627 * for (A *a in b) xxxyy;1628 *1629 * The following code simply scans ahead to the semi to find the actual end.1630 */1631 const char *stmtBuf = SM->getCharacterData(OrigEnd);1632 const char *semiBuf = strchr(stmtBuf, ';');1633 assert(semiBuf && "Can't find ';'");1634 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);1635 InsertText(endBodyLoc, buf);1636 }1637 Stmts.pop_back();1638 ObjCBcLabelNo.pop_back();1639 return nullptr;1640}1641 1642/// RewriteObjCSynchronizedStmt -1643/// This routine rewrites @synchronized(expr) stmt;1644/// into:1645/// objc_sync_enter(expr);1646/// @try stmt @finally { objc_sync_exit(expr); }1647///1648Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {1649 // Get the start location and compute the semi location.1650 SourceLocation startLoc = S->getBeginLoc();1651 const char *startBuf = SM->getCharacterData(startLoc);1652 1653 assert((*startBuf == '@') && "bogus @synchronized location");1654 1655 std::string buf;1656 buf = "objc_sync_enter((id)";1657 const char *lparenBuf = startBuf;1658 while (*lparenBuf != '(') lparenBuf++;1659 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);1660 // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since1661 // the sync expression is typically a message expression that's already1662 // been rewritten! (which implies the SourceLocation's are invalid).1663 SourceLocation endLoc = S->getSynchBody()->getBeginLoc();1664 const char *endBuf = SM->getCharacterData(endLoc);1665 while (*endBuf != ')') endBuf--;1666 SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf);1667 buf = ");\n";1668 // declare a new scope with two variables, _stack and _rethrow.1669 buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";1670 buf += "int buf[18/*32-bit i386*/];\n";1671 buf += "char *pointers[4];} _stack;\n";1672 buf += "id volatile _rethrow = 0;\n";1673 buf += "objc_exception_try_enter(&_stack);\n";1674 buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";1675 ReplaceText(rparenLoc, 1, buf);1676 startLoc = S->getSynchBody()->getEndLoc();1677 startBuf = SM->getCharacterData(startLoc);1678 1679 assert((*startBuf == '}') && "bogus @synchronized block");1680 SourceLocation lastCurlyLoc = startLoc;1681 buf = "}\nelse {\n";1682 buf += " _rethrow = objc_exception_extract(&_stack);\n";1683 buf += "}\n";1684 buf += "{ /* implicit finally clause */\n";1685 buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";1686 1687 std::string syncBuf;1688 syncBuf += " objc_sync_exit(";1689 1690 Expr *syncExpr = S->getSynchExpr();1691 CastKind CK = syncExpr->getType()->isObjCObjectPointerType()1692 ? CK_BitCast :1693 syncExpr->getType()->isBlockPointerType()1694 ? CK_BlockPointerToObjCPointerCast1695 : CK_CPointerToObjCPointerCast;1696 syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),1697 CK, syncExpr);1698 std::string syncExprBufS;1699 llvm::raw_string_ostream syncExprBuf(syncExprBufS);1700 assert(syncExpr != nullptr && "Expected non-null Expr");1701 syncExpr->printPretty(syncExprBuf, nullptr, PrintingPolicy(LangOpts));1702 syncBuf += syncExprBufS;1703 syncBuf += ");";1704 1705 buf += syncBuf;1706 buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n";1707 buf += "}\n";1708 buf += "}";1709 1710 ReplaceText(lastCurlyLoc, 1, buf);1711 1712 bool hasReturns = false;1713 HasReturnStmts(S->getSynchBody(), hasReturns);1714 if (hasReturns)1715 RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);1716 1717 return nullptr;1718}1719 1720void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)1721{1722 // Perform a bottom up traversal of all children.1723 for (Stmt *SubStmt : S->children())1724 if (SubStmt)1725 WarnAboutReturnGotoStmts(SubStmt);1726 1727 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {1728 Diags.Report(Context->getFullLoc(S->getBeginLoc()),1729 TryFinallyContainsReturnDiag);1730 }1731}1732 1733void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns)1734{1735 // Perform a bottom up traversal of all children.1736 for (Stmt *SubStmt : S->children())1737 if (SubStmt)1738 HasReturnStmts(SubStmt, hasReturns);1739 1740 if (isa<ReturnStmt>(S))1741 hasReturns = true;1742}1743 1744void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {1745 // Perform a bottom up traversal of all children.1746 for (Stmt *SubStmt : S->children())1747 if (SubStmt) {1748 RewriteTryReturnStmts(SubStmt);1749 }1750 if (isa<ReturnStmt>(S)) {1751 SourceLocation startLoc = S->getBeginLoc();1752 const char *startBuf = SM->getCharacterData(startLoc);1753 const char *semiBuf = strchr(startBuf, ';');1754 assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");1755 SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);1756 1757 std::string buf;1758 buf = "{ objc_exception_try_exit(&_stack); return";1759 1760 ReplaceText(startLoc, 6, buf);1761 InsertText(onePastSemiLoc, "}");1762 }1763}1764 1765void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {1766 // Perform a bottom up traversal of all children.1767 for (Stmt *SubStmt : S->children())1768 if (SubStmt) {1769 RewriteSyncReturnStmts(SubStmt, syncExitBuf);1770 }1771 if (isa<ReturnStmt>(S)) {1772 SourceLocation startLoc = S->getBeginLoc();1773 const char *startBuf = SM->getCharacterData(startLoc);1774 1775 const char *semiBuf = strchr(startBuf, ';');1776 assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");1777 SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);1778 1779 std::string buf;1780 buf = "{ objc_exception_try_exit(&_stack);";1781 buf += syncExitBuf;1782 buf += " return";1783 1784 ReplaceText(startLoc, 6, buf);1785 InsertText(onePastSemiLoc, "}");1786 }1787}1788 1789Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {1790 // Get the start location and compute the semi location.1791 SourceLocation startLoc = S->getBeginLoc();1792 const char *startBuf = SM->getCharacterData(startLoc);1793 1794 assert((*startBuf == '@') && "bogus @try location");1795 1796 std::string buf;1797 // declare a new scope with two variables, _stack and _rethrow.1798 buf = "/* @try scope begin */ { struct _objc_exception_data {\n";1799 buf += "int buf[18/*32-bit i386*/];\n";1800 buf += "char *pointers[4];} _stack;\n";1801 buf += "id volatile _rethrow = 0;\n";1802 buf += "objc_exception_try_enter(&_stack);\n";1803 buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";1804 1805 ReplaceText(startLoc, 4, buf);1806 1807 startLoc = S->getTryBody()->getEndLoc();1808 startBuf = SM->getCharacterData(startLoc);1809 1810 assert((*startBuf == '}') && "bogus @try block");1811 1812 SourceLocation lastCurlyLoc = startLoc;1813 if (S->getNumCatchStmts()) {1814 startLoc = startLoc.getLocWithOffset(1);1815 buf = " /* @catch begin */ else {\n";1816 buf += " id _caught = objc_exception_extract(&_stack);\n";1817 buf += " objc_exception_try_enter (&_stack);\n";1818 buf += " if (_setjmp(_stack.buf))\n";1819 buf += " _rethrow = objc_exception_extract(&_stack);\n";1820 buf += " else { /* @catch continue */";1821 1822 InsertText(startLoc, buf);1823 } else { /* no catch list */1824 buf = "}\nelse {\n";1825 buf += " _rethrow = objc_exception_extract(&_stack);\n";1826 buf += "}";1827 ReplaceText(lastCurlyLoc, 1, buf);1828 }1829 Stmt *lastCatchBody = nullptr;1830 for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) {1831 ObjCAtCatchStmt *Catch = S->getCatchStmt(I);1832 VarDecl *catchDecl = Catch->getCatchParamDecl();1833 1834 if (I == 0)1835 buf = "if ("; // we are generating code for the first catch clause1836 else1837 buf = "else if (";1838 startLoc = Catch->getBeginLoc();1839 startBuf = SM->getCharacterData(startLoc);1840 1841 assert((*startBuf == '@') && "bogus @catch location");1842 1843 const char *lParenLoc = strchr(startBuf, '(');1844 1845 if (Catch->hasEllipsis()) {1846 // Now rewrite the body...1847 lastCatchBody = Catch->getCatchBody();1848 SourceLocation bodyLoc = lastCatchBody->getBeginLoc();1849 const char *bodyBuf = SM->getCharacterData(bodyLoc);1850 assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' &&1851 "bogus @catch paren location");1852 assert((*bodyBuf == '{') && "bogus @catch body location");1853 1854 buf += "1) { id _tmp = _caught;";1855 Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);1856 } else if (catchDecl) {1857 QualType t = catchDecl->getType();1858 if (t == Context->getObjCIdType()) {1859 buf += "1) { ";1860 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);1861 } else if (const ObjCObjectPointerType *Ptr =1862 t->getAs<ObjCObjectPointerType>()) {1863 // Should be a pointer to a class.1864 ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();1865 if (IDecl) {1866 buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";1867 buf += IDecl->getNameAsString();1868 buf += "\"), (struct objc_object *)_caught)) { ";1869 ReplaceText(startLoc, lParenLoc-startBuf+1, buf);1870 }1871 }1872 // Now rewrite the body...1873 lastCatchBody = Catch->getCatchBody();1874 SourceLocation rParenLoc = Catch->getRParenLoc();1875 SourceLocation bodyLoc = lastCatchBody->getBeginLoc();1876 const char *bodyBuf = SM->getCharacterData(bodyLoc);1877 const char *rParenBuf = SM->getCharacterData(rParenLoc);1878 assert((*rParenBuf == ')') && "bogus @catch paren location");1879 assert((*bodyBuf == '{') && "bogus @catch body location");1880 1881 // Here we replace ") {" with "= _caught;" (which initializes and1882 // declares the @catch parameter).1883 ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;");1884 } else {1885 llvm_unreachable("@catch rewrite bug");1886 }1887 }1888 // Complete the catch list...1889 if (lastCatchBody) {1890 SourceLocation bodyLoc = lastCatchBody->getEndLoc();1891 assert(*SM->getCharacterData(bodyLoc) == '}' &&1892 "bogus @catch body location");1893 1894 // Insert the last (implicit) else clause *before* the right curly brace.1895 bodyLoc = bodyLoc.getLocWithOffset(-1);1896 buf = "} /* last catch end */\n";1897 buf += "else {\n";1898 buf += " _rethrow = _caught;\n";1899 buf += " objc_exception_try_exit(&_stack);\n";1900 buf += "} } /* @catch end */\n";1901 if (!S->getFinallyStmt())1902 buf += "}\n";1903 InsertText(bodyLoc, buf);1904 1905 // Set lastCurlyLoc1906 lastCurlyLoc = lastCatchBody->getEndLoc();1907 }1908 if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {1909 startLoc = finalStmt->getBeginLoc();1910 startBuf = SM->getCharacterData(startLoc);1911 assert((*startBuf == '@') && "bogus @finally start");1912 1913 ReplaceText(startLoc, 8, "/* @finally */");1914 1915 Stmt *body = finalStmt->getFinallyBody();1916 SourceLocation startLoc = body->getBeginLoc();1917 SourceLocation endLoc = body->getEndLoc();1918 assert(*SM->getCharacterData(startLoc) == '{' &&1919 "bogus @finally body location");1920 assert(*SM->getCharacterData(endLoc) == '}' &&1921 "bogus @finally body location");1922 1923 startLoc = startLoc.getLocWithOffset(1);1924 InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n");1925 endLoc = endLoc.getLocWithOffset(-1);1926 InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n");1927 1928 // Set lastCurlyLoc1929 lastCurlyLoc = body->getEndLoc();1930 1931 // Now check for any return/continue/go statements within the @try.1932 WarnAboutReturnGotoStmts(S->getTryBody());1933 } else { /* no finally clause - make sure we synthesize an implicit one */1934 buf = "{ /* implicit finally clause */\n";1935 buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";1936 buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";1937 buf += "}";1938 ReplaceText(lastCurlyLoc, 1, buf);1939 1940 // Now check for any return/continue/go statements within the @try.1941 // The implicit finally clause won't called if the @try contains any1942 // jump statements.1943 bool hasReturns = false;1944 HasReturnStmts(S->getTryBody(), hasReturns);1945 if (hasReturns)1946 RewriteTryReturnStmts(S->getTryBody());1947 }1948 // Now emit the final closing curly brace...1949 lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1);1950 InsertText(lastCurlyLoc, " } /* @try scope end */\n");1951 return nullptr;1952}1953 1954// This can't be done with ReplaceStmt(S, ThrowExpr), since1955// the throw expression is typically a message expression that's already1956// been rewritten! (which implies the SourceLocation's are invalid).1957Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {1958 // Get the start location and compute the semi location.1959 SourceLocation startLoc = S->getBeginLoc();1960 const char *startBuf = SM->getCharacterData(startLoc);1961 1962 assert((*startBuf == '@') && "bogus @throw location");1963 1964 std::string buf;1965 /* void objc_exception_throw(id) __attribute__((noreturn)); */1966 if (S->getThrowExpr())1967 buf = "objc_exception_throw(";1968 else // add an implicit argument1969 buf = "objc_exception_throw(_caught";1970 1971 // handle "@ throw" correctly.1972 const char *wBuf = strchr(startBuf, 'w');1973 assert((*wBuf == 'w') && "@throw: can't find 'w'");1974 ReplaceText(startLoc, wBuf-startBuf+1, buf);1975 1976 const char *semiBuf = strchr(startBuf, ';');1977 assert((*semiBuf == ';') && "@throw: can't find ';'");1978 SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);1979 ReplaceText(semiLoc, 1, ");");1980 return nullptr;1981}1982 1983Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {1984 // Create a new string expression.1985 std::string StrEncoding;1986 Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);1987 Expr *Replacement = getStringLiteral(StrEncoding);1988 ReplaceStmt(Exp, Replacement);1989 1990 // Replace this subexpr in the parent.1991 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.1992 return Replacement;1993}1994 1995Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {1996 if (!SelGetUidFunctionDecl)1997 SynthSelGetUidFunctionDecl();1998 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");1999 // Create a call to sel_registerName("selName").2000 SmallVector<Expr*, 8> SelExprs;2001 SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));2002 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2003 SelExprs);2004 ReplaceStmt(Exp, SelExp);2005 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2006 return SelExp;2007}2008 2009CallExpr *2010RewriteObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,2011 ArrayRef<Expr *> Args,2012 SourceLocation StartLoc,2013 SourceLocation EndLoc) {2014 // Get the type, we will need to reference it in a couple spots.2015 QualType msgSendType = FD->getType();2016 2017 // Create a reference to the objc_msgSend() declaration.2018 DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,2019 VK_LValue, SourceLocation());2020 2021 // Now, we cast the reference to a pointer to the objc_msgSend type.2022 QualType pToFunc = Context->getPointerType(msgSendType);2023 ImplicitCastExpr *ICE =2024 ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,2025 DRE, nullptr, VK_PRValue, FPOptionsOverride());2026 2027 const auto *FT = msgSendType->castAs<FunctionType>();2028 2029 CallExpr *Exp =2030 CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),2031 VK_PRValue, EndLoc, FPOptionsOverride());2032 return Exp;2033}2034 2035static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,2036 const char *&startRef, const char *&endRef) {2037 while (startBuf < endBuf) {2038 if (*startBuf == '<')2039 startRef = startBuf; // mark the start.2040 if (*startBuf == '>') {2041 if (startRef && *startRef == '<') {2042 endRef = startBuf; // mark the end.2043 return true;2044 }2045 return false;2046 }2047 startBuf++;2048 }2049 return false;2050}2051 2052static void scanToNextArgument(const char *&argRef) {2053 int angle = 0;2054 while (*argRef != ')' && (*argRef != ',' || angle > 0)) {2055 if (*argRef == '<')2056 angle++;2057 else if (*argRef == '>')2058 angle--;2059 argRef++;2060 }2061 assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");2062}2063 2064bool RewriteObjC::needToScanForQualifiers(QualType T) {2065 if (T->isObjCQualifiedIdType())2066 return true;2067 if (const PointerType *PT = T->getAs<PointerType>()) {2068 if (PT->getPointeeType()->isObjCQualifiedIdType())2069 return true;2070 }2071 if (T->isObjCObjectPointerType()) {2072 T = T->getPointeeType();2073 return T->isObjCQualifiedInterfaceType();2074 }2075 if (T->isArrayType()) {2076 QualType ElemTy = Context->getBaseElementType(T);2077 return needToScanForQualifiers(ElemTy);2078 }2079 return false;2080}2081 2082void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {2083 QualType Type = E->getType();2084 if (needToScanForQualifiers(Type)) {2085 SourceLocation Loc, EndLoc;2086 2087 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {2088 Loc = ECE->getLParenLoc();2089 EndLoc = ECE->getRParenLoc();2090 } else {2091 Loc = E->getBeginLoc();2092 EndLoc = E->getEndLoc();2093 }2094 // This will defend against trying to rewrite synthesized expressions.2095 if (Loc.isInvalid() || EndLoc.isInvalid())2096 return;2097 2098 const char *startBuf = SM->getCharacterData(Loc);2099 const char *endBuf = SM->getCharacterData(EndLoc);2100 const char *startRef = nullptr, *endRef = nullptr;2101 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2102 // Get the locations of the startRef, endRef.2103 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);2104 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);2105 // Comment out the protocol references.2106 InsertText(LessLoc, "/*");2107 InsertText(GreaterLoc, "*/");2108 }2109 }2110}2111 2112void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {2113 SourceLocation Loc;2114 QualType Type;2115 const FunctionProtoType *proto = nullptr;2116 if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {2117 Loc = VD->getLocation();2118 Type = VD->getType();2119 }2120 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {2121 Loc = FD->getLocation();2122 // Check for ObjC 'id' and class types that have been adorned with protocol2123 // information (id<p>, C<p>*). The protocol references need to be rewritten!2124 const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2125 assert(funcType && "missing function type");2126 proto = dyn_cast<FunctionProtoType>(funcType);2127 if (!proto)2128 return;2129 Type = proto->getReturnType();2130 }2131 else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {2132 Loc = FD->getLocation();2133 Type = FD->getType();2134 }2135 else2136 return;2137 2138 if (needToScanForQualifiers(Type)) {2139 // Since types are unique, we need to scan the buffer.2140 2141 const char *endBuf = SM->getCharacterData(Loc);2142 const char *startBuf = endBuf;2143 while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)2144 startBuf--; // scan backward (from the decl location) for return type.2145 const char *startRef = nullptr, *endRef = nullptr;2146 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2147 // Get the locations of the startRef, endRef.2148 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);2149 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);2150 // Comment out the protocol references.2151 InsertText(LessLoc, "/*");2152 InsertText(GreaterLoc, "*/");2153 }2154 }2155 if (!proto)2156 return; // most likely, was a variable2157 // Now check arguments.2158 const char *startBuf = SM->getCharacterData(Loc);2159 const char *startFuncBuf = startBuf;2160 for (unsigned i = 0; i < proto->getNumParams(); i++) {2161 if (needToScanForQualifiers(proto->getParamType(i))) {2162 // Since types are unique, we need to scan the buffer.2163 2164 const char *endBuf = startBuf;2165 // scan forward (from the decl location) for argument types.2166 scanToNextArgument(endBuf);2167 const char *startRef = nullptr, *endRef = nullptr;2168 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2169 // Get the locations of the startRef, endRef.2170 SourceLocation LessLoc =2171 Loc.getLocWithOffset(startRef-startFuncBuf);2172 SourceLocation GreaterLoc =2173 Loc.getLocWithOffset(endRef-startFuncBuf+1);2174 // Comment out the protocol references.2175 InsertText(LessLoc, "/*");2176 InsertText(GreaterLoc, "*/");2177 }2178 startBuf = ++endBuf;2179 }2180 else {2181 // If the function name is derived from a macro expansion, then the2182 // argument buffer will not follow the name. Need to speak with Chris.2183 while (*startBuf && *startBuf != ')' && *startBuf != ',')2184 startBuf++; // scan forward (from the decl location) for argument types.2185 startBuf++;2186 }2187 }2188}2189 2190void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) {2191 QualType QT = ND->getType();2192 const Type* TypePtr = QT->getAs<Type>();2193 if (!isa<TypeOfExprType>(TypePtr))2194 return;2195 while (isa<TypeOfExprType>(TypePtr)) {2196 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);2197 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();2198 TypePtr = QT->getAs<Type>();2199 }2200 // FIXME. This will not work for multiple declarators; as in:2201 // __typeof__(a) b,c,d;2202 std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));2203 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();2204 const char *startBuf = SM->getCharacterData(DeclLoc);2205 if (ND->getInit()) {2206 std::string Name(ND->getNameAsString());2207 TypeAsString += " " + Name + " = ";2208 Expr *E = ND->getInit();2209 SourceLocation startLoc;2210 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))2211 startLoc = ECE->getLParenLoc();2212 else2213 startLoc = E->getBeginLoc();2214 startLoc = SM->getExpansionLoc(startLoc);2215 const char *endBuf = SM->getCharacterData(startLoc);2216 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2217 }2218 else {2219 SourceLocation X = ND->getEndLoc();2220 X = SM->getExpansionLoc(X);2221 const char *endBuf = SM->getCharacterData(X);2222 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2223 }2224}2225 2226// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);2227void RewriteObjC::SynthSelGetUidFunctionDecl() {2228 IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");2229 SmallVector<QualType, 16> ArgTys;2230 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2231 QualType getFuncType =2232 getSimpleFunctionType(Context->getObjCSelType(), ArgTys);2233 SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2234 SourceLocation(),2235 SourceLocation(),2236 SelGetUidIdent, getFuncType,2237 nullptr, SC_Extern);2238}2239 2240void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {2241 // declared in <objc/objc.h>2242 if (FD->getIdentifier() &&2243 FD->getName() == "sel_registerName") {2244 SelGetUidFunctionDecl = FD;2245 return;2246 }2247 RewriteObjCQualifiedInterfaceTypes(FD);2248}2249 2250void RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {2251 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2252 const char *argPtr = TypeString.c_str();2253 if (!strchr(argPtr, '^')) {2254 Str += TypeString;2255 return;2256 }2257 while (*argPtr) {2258 Str += (*argPtr == '^' ? '*' : *argPtr);2259 argPtr++;2260 }2261}2262 2263// FIXME. Consolidate this routine with RewriteBlockPointerType.2264void RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str,2265 ValueDecl *VD) {2266 QualType Type = VD->getType();2267 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2268 const char *argPtr = TypeString.c_str();2269 int paren = 0;2270 while (*argPtr) {2271 switch (*argPtr) {2272 case '(':2273 Str += *argPtr;2274 paren++;2275 break;2276 case ')':2277 Str += *argPtr;2278 paren--;2279 break;2280 case '^':2281 Str += '*';2282 if (paren == 1)2283 Str += VD->getNameAsString();2284 break;2285 default:2286 Str += *argPtr;2287 break;2288 }2289 argPtr++;2290 }2291}2292 2293void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {2294 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();2295 const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2296 const FunctionProtoType *proto = dyn_cast_or_null<FunctionProtoType>(funcType);2297 if (!proto)2298 return;2299 QualType Type = proto->getReturnType();2300 std::string FdStr = Type.getAsString(Context->getPrintingPolicy());2301 FdStr += " ";2302 FdStr += FD->getName();2303 FdStr += "(";2304 unsigned numArgs = proto->getNumParams();2305 for (unsigned i = 0; i < numArgs; i++) {2306 QualType ArgType = proto->getParamType(i);2307 RewriteBlockPointerType(FdStr, ArgType);2308 if (i+1 < numArgs)2309 FdStr += ", ";2310 }2311 FdStr += ");\n";2312 InsertText(FunLocStart, FdStr);2313 CurFunctionDeclToDeclareForBlock = nullptr;2314}2315 2316// SynthSuperConstructorFunctionDecl - id objc_super(id obj, id super);2317void RewriteObjC::SynthSuperConstructorFunctionDecl() {2318 if (SuperConstructorFunctionDecl)2319 return;2320 IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");2321 SmallVector<QualType, 16> ArgTys;2322 QualType argT = Context->getObjCIdType();2323 assert(!argT.isNull() && "Can't find 'id' type");2324 ArgTys.push_back(argT);2325 ArgTys.push_back(argT);2326 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2327 ArgTys);2328 SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2329 SourceLocation(),2330 SourceLocation(),2331 msgSendIdent, msgSendType,2332 nullptr, SC_Extern);2333}2334 2335// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);2336void RewriteObjC::SynthMsgSendFunctionDecl() {2337 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");2338 SmallVector<QualType, 16> ArgTys;2339 QualType argT = Context->getObjCIdType();2340 assert(!argT.isNull() && "Can't find 'id' type");2341 ArgTys.push_back(argT);2342 argT = Context->getObjCSelType();2343 assert(!argT.isNull() && "Can't find 'SEL' type");2344 ArgTys.push_back(argT);2345 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2346 ArgTys, /*variadic=*/true);2347 MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2348 SourceLocation(),2349 SourceLocation(),2350 msgSendIdent, msgSendType,2351 nullptr, SC_Extern);2352}2353 2354// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);2355void RewriteObjC::SynthMsgSendSuperFunctionDecl() {2356 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");2357 SmallVector<QualType, 16> ArgTys;2358 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,2359 SourceLocation(), SourceLocation(),2360 &Context->Idents.get("objc_super"));2361 QualType argT = Context->getPointerType(Context->getCanonicalTagType(RD));2362 assert(!argT.isNull() && "Can't build 'struct objc_super *' type");2363 ArgTys.push_back(argT);2364 argT = Context->getObjCSelType();2365 assert(!argT.isNull() && "Can't find 'SEL' type");2366 ArgTys.push_back(argT);2367 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2368 ArgTys, /*variadic=*/true);2369 MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2370 SourceLocation(),2371 SourceLocation(),2372 msgSendIdent, msgSendType,2373 nullptr, SC_Extern);2374}2375 2376// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);2377void RewriteObjC::SynthMsgSendStretFunctionDecl() {2378 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");2379 SmallVector<QualType, 16> ArgTys;2380 QualType argT = Context->getObjCIdType();2381 assert(!argT.isNull() && "Can't find 'id' type");2382 ArgTys.push_back(argT);2383 argT = Context->getObjCSelType();2384 assert(!argT.isNull() && "Can't find 'SEL' type");2385 ArgTys.push_back(argT);2386 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2387 ArgTys, /*variadic=*/true);2388 MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2389 SourceLocation(),2390 SourceLocation(),2391 msgSendIdent, msgSendType,2392 nullptr, SC_Extern);2393}2394 2395// SynthMsgSendSuperStretFunctionDecl -2396// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);2397void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {2398 IdentifierInfo *msgSendIdent =2399 &Context->Idents.get("objc_msgSendSuper_stret");2400 SmallVector<QualType, 16> ArgTys;2401 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,2402 SourceLocation(), SourceLocation(),2403 &Context->Idents.get("objc_super"));2404 QualType argT = Context->getPointerType(Context->getCanonicalTagType(RD));2405 assert(!argT.isNull() && "Can't build 'struct objc_super *' type");2406 ArgTys.push_back(argT);2407 argT = Context->getObjCSelType();2408 assert(!argT.isNull() && "Can't find 'SEL' type");2409 ArgTys.push_back(argT);2410 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2411 ArgTys, /*variadic=*/true);2412 MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2413 SourceLocation(),2414 SourceLocation(),2415 msgSendIdent,2416 msgSendType, nullptr,2417 SC_Extern);2418}2419 2420// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);2421void RewriteObjC::SynthMsgSendFpretFunctionDecl() {2422 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");2423 SmallVector<QualType, 16> ArgTys;2424 QualType argT = Context->getObjCIdType();2425 assert(!argT.isNull() && "Can't find 'id' type");2426 ArgTys.push_back(argT);2427 argT = Context->getObjCSelType();2428 assert(!argT.isNull() && "Can't find 'SEL' type");2429 ArgTys.push_back(argT);2430 QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,2431 ArgTys, /*variadic=*/true);2432 MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2433 SourceLocation(),2434 SourceLocation(),2435 msgSendIdent, msgSendType,2436 nullptr, SC_Extern);2437}2438 2439// SynthGetClassFunctionDecl - id objc_getClass(const char *name);2440void RewriteObjC::SynthGetClassFunctionDecl() {2441 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");2442 SmallVector<QualType, 16> ArgTys;2443 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2444 QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),2445 ArgTys);2446 GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2447 SourceLocation(),2448 SourceLocation(),2449 getClassIdent, getClassType,2450 nullptr, SC_Extern);2451}2452 2453// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);2454void RewriteObjC::SynthGetSuperClassFunctionDecl() {2455 IdentifierInfo *getSuperClassIdent =2456 &Context->Idents.get("class_getSuperclass");2457 SmallVector<QualType, 16> ArgTys;2458 ArgTys.push_back(Context->getObjCClassType());2459 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2460 ArgTys);2461 GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2462 SourceLocation(),2463 SourceLocation(),2464 getSuperClassIdent,2465 getClassType, nullptr,2466 SC_Extern);2467}2468 2469// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name);2470void RewriteObjC::SynthGetMetaClassFunctionDecl() {2471 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");2472 SmallVector<QualType, 16> ArgTys;2473 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2474 QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(),2475 ArgTys);2476 GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2477 SourceLocation(),2478 SourceLocation(),2479 getClassIdent, getClassType,2480 nullptr, SC_Extern);2481}2482 2483Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {2484 assert(Exp != nullptr && "Expected non-null ObjCStringLiteral");2485 QualType strType = getConstantStringStructType();2486 2487 std::string S = "__NSConstantStringImpl_";2488 2489 std::string tmpName = InFileName;2490 unsigned i;2491 for (i=0; i < tmpName.length(); i++) {2492 char c = tmpName.at(i);2493 // replace any non-alphanumeric characters with '_'.2494 if (!isAlphanumeric(c))2495 tmpName[i] = '_';2496 }2497 S += tmpName;2498 S += "_";2499 S += utostr(NumObjCStringLiterals++);2500 2501 Preamble += "static __NSConstantStringImpl " + S;2502 Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";2503 Preamble += "0x000007c8,"; // utf8_str2504 // The pretty printer for StringLiteral handles escape characters properly.2505 std::string prettyBufS;2506 llvm::raw_string_ostream prettyBuf(prettyBufS);2507 Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));2508 Preamble += prettyBufS;2509 Preamble += ",";2510 Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";2511 2512 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),2513 SourceLocation(), &Context->Idents.get(S),2514 strType, nullptr, SC_Static);2515 DeclRefExpr *DRE = new (Context)2516 DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());2517 Expr *Unop = UnaryOperator::Create(2518 const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,2519 Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,2520 SourceLocation(), false, FPOptionsOverride());2521 // cast to NSConstantString *2522 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),2523 CK_CPointerToObjCPointerCast, Unop);2524 ReplaceStmt(Exp, cast);2525 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2526 return cast;2527}2528 2529// struct objc_super { struct objc_object *receiver; struct objc_class *super; };2530QualType RewriteObjC::getSuperStructType() {2531 if (!SuperStructDecl) {2532 SuperStructDecl = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,2533 SourceLocation(), SourceLocation(),2534 &Context->Idents.get("objc_super"));2535 QualType FieldTypes[2];2536 2537 // struct objc_object *receiver;2538 FieldTypes[0] = Context->getObjCIdType();2539 // struct objc_class *super;2540 FieldTypes[1] = Context->getObjCClassType();2541 2542 // Create fields2543 for (unsigned i = 0; i < 2; ++i) {2544 SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,2545 SourceLocation(),2546 SourceLocation(), nullptr,2547 FieldTypes[i], nullptr,2548 /*BitWidth=*/nullptr,2549 /*Mutable=*/false,2550 ICIS_NoInit));2551 }2552 2553 SuperStructDecl->completeDefinition();2554 }2555 return Context->getCanonicalTagType(SuperStructDecl);2556}2557 2558QualType RewriteObjC::getConstantStringStructType() {2559 if (!ConstantStringDecl) {2560 ConstantStringDecl = RecordDecl::Create(2561 *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),2562 SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));2563 QualType FieldTypes[4];2564 2565 // struct objc_object *receiver;2566 FieldTypes[0] = Context->getObjCIdType();2567 // int flags;2568 FieldTypes[1] = Context->IntTy;2569 // char *str;2570 FieldTypes[2] = Context->getPointerType(Context->CharTy);2571 // long length;2572 FieldTypes[3] = Context->LongTy;2573 2574 // Create fields2575 for (unsigned i = 0; i < 4; ++i) {2576 ConstantStringDecl->addDecl(FieldDecl::Create(*Context,2577 ConstantStringDecl,2578 SourceLocation(),2579 SourceLocation(), nullptr,2580 FieldTypes[i], nullptr,2581 /*BitWidth=*/nullptr,2582 /*Mutable=*/true,2583 ICIS_NoInit));2584 }2585 2586 ConstantStringDecl->completeDefinition();2587 }2588 return Context->getCanonicalTagType(ConstantStringDecl);2589}2590 2591CallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,2592 QualType msgSendType,2593 QualType returnType,2594 SmallVectorImpl<QualType> &ArgTypes,2595 SmallVectorImpl<Expr*> &MsgExprs,2596 ObjCMethodDecl *Method) {2597 // Create a reference to the objc_msgSend_stret() declaration.2598 DeclRefExpr *STDRE =2599 new (Context) DeclRefExpr(*Context, MsgSendStretFlavor, false,2600 msgSendType, VK_LValue, SourceLocation());2601 // Need to cast objc_msgSend_stret to "void *" (see above comment).2602 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context,2603 Context->getPointerType(Context->VoidTy),2604 CK_BitCast, STDRE);2605 // Now do the "normal" pointer to function cast.2606 QualType castType = getSimpleFunctionType(returnType, ArgTypes,2607 Method ? Method->isVariadic()2608 : false);2609 castType = Context->getPointerType(castType);2610 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2611 cast);2612 2613 // Don't forget the parens to enforce the proper binding.2614 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);2615 2616 const auto *FT = msgSendType->castAs<FunctionType>();2617 CallExpr *STCE =2618 CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(), VK_PRValue,2619 SourceLocation(), FPOptionsOverride());2620 return STCE;2621}2622 2623Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp,2624 SourceLocation StartLoc,2625 SourceLocation EndLoc) {2626 if (!SelGetUidFunctionDecl)2627 SynthSelGetUidFunctionDecl();2628 if (!MsgSendFunctionDecl)2629 SynthMsgSendFunctionDecl();2630 if (!MsgSendSuperFunctionDecl)2631 SynthMsgSendSuperFunctionDecl();2632 if (!MsgSendStretFunctionDecl)2633 SynthMsgSendStretFunctionDecl();2634 if (!MsgSendSuperStretFunctionDecl)2635 SynthMsgSendSuperStretFunctionDecl();2636 if (!MsgSendFpretFunctionDecl)2637 SynthMsgSendFpretFunctionDecl();2638 if (!GetClassFunctionDecl)2639 SynthGetClassFunctionDecl();2640 if (!GetSuperClassFunctionDecl)2641 SynthGetSuperClassFunctionDecl();2642 if (!GetMetaClassFunctionDecl)2643 SynthGetMetaClassFunctionDecl();2644 2645 // default to objc_msgSend().2646 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2647 // May need to use objc_msgSend_stret() as well.2648 FunctionDecl *MsgSendStretFlavor = nullptr;2649 if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {2650 QualType resultType = mDecl->getReturnType();2651 if (resultType->isRecordType())2652 MsgSendStretFlavor = MsgSendStretFunctionDecl;2653 else if (resultType->isRealFloatingType())2654 MsgSendFlavor = MsgSendFpretFunctionDecl;2655 }2656 2657 // Synthesize a call to objc_msgSend().2658 SmallVector<Expr*, 8> MsgExprs;2659 switch (Exp->getReceiverKind()) {2660 case ObjCMessageExpr::SuperClass: {2661 MsgSendFlavor = MsgSendSuperFunctionDecl;2662 if (MsgSendStretFlavor)2663 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;2664 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");2665 2666 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();2667 2668 SmallVector<Expr*, 4> InitExprs;2669 2670 // set the receiver to self, the first argument to all methods.2671 InitExprs.push_back(NoTypeInfoCStyleCastExpr(2672 Context, Context->getObjCIdType(), CK_BitCast,2673 new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,2674 Context->getObjCIdType(), VK_PRValue,2675 SourceLocation()))); // set the 'receiver'.2676 2677 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))2678 SmallVector<Expr*, 8> ClsExprs;2679 ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));2680 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,2681 ClsExprs, StartLoc, EndLoc);2682 // (Class)objc_getClass("CurrentClass")2683 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,2684 Context->getObjCClassType(),2685 CK_BitCast, Cls);2686 ClsExprs.clear();2687 ClsExprs.push_back(ArgExpr);2688 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,2689 StartLoc, EndLoc);2690 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))2691 // To turn off a warning, type-cast to 'id'2692 InitExprs.push_back( // set 'super class', using class_getSuperclass().2693 NoTypeInfoCStyleCastExpr(Context,2694 Context->getObjCIdType(),2695 CK_BitCast, Cls));2696 // struct objc_super2697 QualType superType = getSuperStructType();2698 Expr *SuperRep;2699 2700 if (LangOpts.MicrosoftExt) {2701 SynthSuperConstructorFunctionDecl();2702 // Simulate a constructor call...2703 DeclRefExpr *DRE = new (Context)2704 DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,2705 VK_LValue, SourceLocation());2706 SuperRep =2707 CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,2708 SourceLocation(), FPOptionsOverride());2709 // The code for super is a little tricky to prevent collision with2710 // the structure definition in the header. The rewriter has it's own2711 // internal definition (__rw_objc_super) that is uses. This is why2712 // we need the cast below. For example:2713 // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))2714 //2715 SuperRep = UnaryOperator::Create(2716 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,2717 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,2718 SourceLocation(), false, FPOptionsOverride());2719 SuperRep = NoTypeInfoCStyleCastExpr(Context,2720 Context->getPointerType(superType),2721 CK_BitCast, SuperRep);2722 } else {2723 // (struct objc_super) { <exprs from above> }2724 InitListExpr *ILE =2725 new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,2726 SourceLocation());2727 TypeSourceInfo *superTInfo2728 = Context->getTrivialTypeSourceInfo(superType);2729 SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,2730 superType, VK_LValue,2731 ILE, false);2732 // struct objc_super *2733 SuperRep = UnaryOperator::Create(2734 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,2735 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,2736 SourceLocation(), false, FPOptionsOverride());2737 }2738 MsgExprs.push_back(SuperRep);2739 break;2740 }2741 2742 case ObjCMessageExpr::Class: {2743 SmallVector<Expr*, 8> ClsExprs;2744 auto *Class =2745 Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();2746 IdentifierInfo *clsName = Class->getIdentifier();2747 ClsExprs.push_back(getStringLiteral(clsName->getName()));2748 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2749 StartLoc, EndLoc);2750 MsgExprs.push_back(Cls);2751 break;2752 }2753 2754 case ObjCMessageExpr::SuperInstance:{2755 MsgSendFlavor = MsgSendSuperFunctionDecl;2756 if (MsgSendStretFlavor)2757 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;2758 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");2759 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();2760 SmallVector<Expr*, 4> InitExprs;2761 2762 InitExprs.push_back(NoTypeInfoCStyleCastExpr(2763 Context, Context->getObjCIdType(), CK_BitCast,2764 new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,2765 Context->getObjCIdType(), VK_PRValue,2766 SourceLocation()))); // set the 'receiver'.2767 2768 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))2769 SmallVector<Expr*, 8> ClsExprs;2770 ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));2771 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2772 StartLoc, EndLoc);2773 // (Class)objc_getClass("CurrentClass")2774 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,2775 Context->getObjCClassType(),2776 CK_BitCast, Cls);2777 ClsExprs.clear();2778 ClsExprs.push_back(ArgExpr);2779 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,2780 StartLoc, EndLoc);2781 2782 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))2783 // To turn off a warning, type-cast to 'id'2784 InitExprs.push_back(2785 // set 'super class', using class_getSuperclass().2786 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),2787 CK_BitCast, Cls));2788 // struct objc_super2789 QualType superType = getSuperStructType();2790 Expr *SuperRep;2791 2792 if (LangOpts.MicrosoftExt) {2793 SynthSuperConstructorFunctionDecl();2794 // Simulate a constructor call...2795 DeclRefExpr *DRE = new (Context)2796 DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,2797 VK_LValue, SourceLocation());2798 SuperRep =2799 CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,2800 SourceLocation(), FPOptionsOverride());2801 // The code for super is a little tricky to prevent collision with2802 // the structure definition in the header. The rewriter has it's own2803 // internal definition (__rw_objc_super) that is uses. This is why2804 // we need the cast below. For example:2805 // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))2806 //2807 SuperRep = UnaryOperator::Create(2808 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,2809 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,2810 SourceLocation(), false, FPOptionsOverride());2811 SuperRep = NoTypeInfoCStyleCastExpr(Context,2812 Context->getPointerType(superType),2813 CK_BitCast, SuperRep);2814 } else {2815 // (struct objc_super) { <exprs from above> }2816 InitListExpr *ILE =2817 new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,2818 SourceLocation());2819 TypeSourceInfo *superTInfo2820 = Context->getTrivialTypeSourceInfo(superType);2821 SuperRep = new (Context) CompoundLiteralExpr(2822 SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);2823 }2824 MsgExprs.push_back(SuperRep);2825 break;2826 }2827 2828 case ObjCMessageExpr::Instance: {2829 // Remove all type-casts because it may contain objc-style types; e.g.2830 // Foo<Proto> *.2831 Expr *recExpr = Exp->getInstanceReceiver();2832 while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))2833 recExpr = CE->getSubExpr();2834 CastKind CK = recExpr->getType()->isObjCObjectPointerType()2835 ? CK_BitCast : recExpr->getType()->isBlockPointerType()2836 ? CK_BlockPointerToObjCPointerCast2837 : CK_CPointerToObjCPointerCast;2838 2839 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),2840 CK, recExpr);2841 MsgExprs.push_back(recExpr);2842 break;2843 }2844 }2845 2846 // Create a call to sel_registerName("selName"), it will be the 2nd argument.2847 SmallVector<Expr*, 8> SelExprs;2848 SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));2849 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2850 SelExprs, StartLoc, EndLoc);2851 MsgExprs.push_back(SelExp);2852 2853 // Now push any user supplied arguments.2854 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {2855 Expr *userExpr = Exp->getArg(i);2856 // Make all implicit casts explicit...ICE comes in handy:-)2857 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {2858 // Reuse the ICE type, it is exactly what the doctor ordered.2859 QualType type = ICE->getType();2860 if (needToScanForQualifiers(type))2861 type = Context->getObjCIdType();2862 // Make sure we convert "type (^)(...)" to "type (*)(...)".2863 (void)convertBlockPointerToFunctionPointer(type);2864 const Expr *SubExpr = ICE->IgnoreParenImpCasts();2865 CastKind CK;2866 if (SubExpr->getType()->isIntegralType(*Context) &&2867 type->isBooleanType()) {2868 CK = CK_IntegralToBoolean;2869 } else if (type->isObjCObjectPointerType()) {2870 if (SubExpr->getType()->isBlockPointerType()) {2871 CK = CK_BlockPointerToObjCPointerCast;2872 } else if (SubExpr->getType()->isPointerType()) {2873 CK = CK_CPointerToObjCPointerCast;2874 } else {2875 CK = CK_BitCast;2876 }2877 } else {2878 CK = CK_BitCast;2879 }2880 2881 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);2882 }2883 // Make id<P...> cast into an 'id' cast.2884 else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {2885 if (CE->getType()->isObjCQualifiedIdType()) {2886 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))2887 userExpr = CE->getSubExpr();2888 CastKind CK;2889 if (userExpr->getType()->isIntegralType(*Context)) {2890 CK = CK_IntegralToPointer;2891 } else if (userExpr->getType()->isBlockPointerType()) {2892 CK = CK_BlockPointerToObjCPointerCast;2893 } else if (userExpr->getType()->isPointerType()) {2894 CK = CK_CPointerToObjCPointerCast;2895 } else {2896 CK = CK_BitCast;2897 }2898 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),2899 CK, userExpr);2900 }2901 }2902 MsgExprs.push_back(userExpr);2903 // We've transferred the ownership to MsgExprs. For now, we *don't* null2904 // out the argument in the original expression (since we aren't deleting2905 // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.2906 //Exp->setArg(i, 0);2907 }2908 // Generate the funky cast.2909 CastExpr *cast;2910 SmallVector<QualType, 8> ArgTypes;2911 QualType returnType;2912 2913 // Push 'id' and 'SEL', the 2 implicit arguments.2914 if (MsgSendFlavor == MsgSendSuperFunctionDecl)2915 ArgTypes.push_back(Context->getPointerType(getSuperStructType()));2916 else2917 ArgTypes.push_back(Context->getObjCIdType());2918 ArgTypes.push_back(Context->getObjCSelType());2919 if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {2920 // Push any user argument types.2921 for (const auto *PI : OMD->parameters()) {2922 QualType t = PI->getType()->isObjCQualifiedIdType()2923 ? Context->getObjCIdType()2924 : PI->getType();2925 // Make sure we convert "t (^)(...)" to "t (*)(...)".2926 (void)convertBlockPointerToFunctionPointer(t);2927 ArgTypes.push_back(t);2928 }2929 returnType = Exp->getType();2930 convertToUnqualifiedObjCType(returnType);2931 (void)convertBlockPointerToFunctionPointer(returnType);2932 } else {2933 returnType = Context->getObjCIdType();2934 }2935 // Get the type, we will need to reference it in a couple spots.2936 QualType msgSendType = MsgSendFlavor->getType();2937 2938 // Create a reference to the objc_msgSend() declaration.2939 DeclRefExpr *DRE = new (Context) DeclRefExpr(2940 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());2941 2942 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).2943 // If we don't do this cast, we get the following bizarre warning/note:2944 // xx.m:13: warning: function called through a non-compatible type2945 // xx.m:13: note: if this code is reached, the program will abort2946 cast = NoTypeInfoCStyleCastExpr(Context,2947 Context->getPointerType(Context->VoidTy),2948 CK_BitCast, DRE);2949 2950 // Now do the "normal" pointer to function cast.2951 // If we don't have a method decl, force a variadic cast.2952 const ObjCMethodDecl *MD = Exp->getMethodDecl();2953 QualType castType =2954 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);2955 castType = Context->getPointerType(castType);2956 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2957 cast);2958 2959 // Don't forget the parens to enforce the proper binding.2960 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);2961 2962 const auto *FT = msgSendType->castAs<FunctionType>();2963 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2964 VK_PRValue, EndLoc, FPOptionsOverride());2965 Stmt *ReplacingStmt = CE;2966 if (MsgSendStretFlavor) {2967 // We have the method which returns a struct/union. Must also generate2968 // call to objc_msgSend_stret and hang both varieties on a conditional2969 // expression which dictate which one to envoke depending on size of2970 // method's return type.2971 2972 CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,2973 msgSendType, returnType,2974 ArgTypes, MsgExprs,2975 Exp->getMethodDecl());2976 2977 // Build sizeof(returnType)2978 UnaryExprOrTypeTraitExpr *sizeofExpr =2979 new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf,2980 Context->getTrivialTypeSourceInfo(returnType),2981 Context->getSizeType(), SourceLocation(),2982 SourceLocation());2983 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))2984 // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.2985 // For X86 it is more complicated and some kind of target specific routine2986 // is needed to decide what to do.2987 unsigned IntSize =2988 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));2989 IntegerLiteral *limit = IntegerLiteral::Create(*Context,2990 llvm::APInt(IntSize, 8),2991 Context->IntTy,2992 SourceLocation());2993 BinaryOperator *lessThanExpr = BinaryOperator::Create(2994 *Context, sizeofExpr, limit, BO_LE, Context->IntTy, VK_PRValue,2995 OK_Ordinary, SourceLocation(), FPOptionsOverride());2996 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))2997 ConditionalOperator *CondExpr = new (Context) ConditionalOperator(2998 lessThanExpr, SourceLocation(), CE, SourceLocation(), STCE, returnType,2999 VK_PRValue, OK_Ordinary);3000 ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(),3001 CondExpr);3002 }3003 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3004 return ReplacingStmt;3005}3006 3007Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {3008 Stmt *ReplacingStmt =3009 SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());3010 3011 // Now do the actual rewrite.3012 ReplaceStmt(Exp, ReplacingStmt);3013 3014 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3015 return ReplacingStmt;3016}3017 3018// typedef struct objc_object Protocol;3019QualType RewriteObjC::getProtocolType() {3020 if (!ProtocolTypeDecl) {3021 TypeSourceInfo *TInfo3022 = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());3023 ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,3024 SourceLocation(), SourceLocation(),3025 &Context->Idents.get("Protocol"),3026 TInfo);3027 }3028 return Context->getTypeDeclType(ProtocolTypeDecl);3029}3030 3031/// RewriteObjCProtocolExpr - Rewrite a protocol expression into3032/// a synthesized/forward data reference (to the protocol's metadata).3033/// The forward references (and metadata) are generated in3034/// RewriteObjC::HandleTranslationUnit().3035Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {3036 std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();3037 IdentifierInfo *ID = &Context->Idents.get(Name);3038 VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),3039 SourceLocation(), ID, getProtocolType(),3040 nullptr, SC_Extern);3041 DeclRefExpr *DRE = new (Context) DeclRefExpr(3042 *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());3043 Expr *DerefExpr = UnaryOperator::Create(3044 const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,3045 Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,3046 SourceLocation(), false, FPOptionsOverride());3047 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),3048 CK_BitCast,3049 DerefExpr);3050 ReplaceStmt(Exp, castExpr);3051 ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());3052 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3053 return castExpr;3054}3055 3056bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,3057 const char *endBuf) {3058 while (startBuf < endBuf) {3059 if (*startBuf == '#') {3060 // Skip whitespace.3061 for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)3062 ;3063 if (!strncmp(startBuf, "if", strlen("if")) ||3064 !strncmp(startBuf, "ifdef", strlen("ifdef")) ||3065 !strncmp(startBuf, "ifndef", strlen("ifndef")) ||3066 !strncmp(startBuf, "define", strlen("define")) ||3067 !strncmp(startBuf, "undef", strlen("undef")) ||3068 !strncmp(startBuf, "else", strlen("else")) ||3069 !strncmp(startBuf, "elif", strlen("elif")) ||3070 !strncmp(startBuf, "endif", strlen("endif")) ||3071 !strncmp(startBuf, "pragma", strlen("pragma")) ||3072 !strncmp(startBuf, "include", strlen("include")) ||3073 !strncmp(startBuf, "import", strlen("import")) ||3074 !strncmp(startBuf, "include_next", strlen("include_next")))3075 return true;3076 }3077 startBuf++;3078 }3079 return false;3080}3081 3082/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to3083/// an objective-c class with ivars.3084void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,3085 std::string &Result) {3086 assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");3087 assert(CDecl->getName() != "" &&3088 "Name missing in SynthesizeObjCInternalStruct");3089 // Do not synthesize more than once.3090 if (ObjCSynthesizedStructs.count(CDecl))3091 return;3092 ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();3093 int NumIvars = CDecl->ivar_size();3094 SourceLocation LocStart = CDecl->getBeginLoc();3095 SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();3096 3097 const char *startBuf = SM->getCharacterData(LocStart);3098 const char *endBuf = SM->getCharacterData(LocEnd);3099 3100 // If no ivars and no root or if its root, directly or indirectly,3101 // have no ivars (thus not synthesized) then no need to synthesize this class.3102 if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) &&3103 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {3104 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3105 ReplaceText(LocStart, endBuf-startBuf, Result);3106 return;3107 }3108 3109 // FIXME: This has potential of causing problem. If3110 // SynthesizeObjCInternalStruct is ever called recursively.3111 Result += "\nstruct ";3112 Result += CDecl->getNameAsString();3113 if (LangOpts.MicrosoftExt)3114 Result += "_IMPL";3115 3116 if (NumIvars > 0) {3117 const char *cursor = strchr(startBuf, '{');3118 assert((cursor && endBuf)3119 && "SynthesizeObjCInternalStruct - malformed @interface");3120 // If the buffer contains preprocessor directives, we do more fine-grained3121 // rewrites. This is intended to fix code that looks like (which occurs in3122 // NSURL.h, for example):3123 //3124 // #ifdef XYZ3125 // @interface Foo : NSObject3126 // #else3127 // @interface FooBar : NSObject3128 // #endif3129 // {3130 // int i;3131 // }3132 // @end3133 //3134 // This clause is segregated to avoid breaking the common case.3135 if (BufferContainsPPDirectives(startBuf, cursor)) {3136 SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :3137 CDecl->getAtStartLoc();3138 const char *endHeader = SM->getCharacterData(L);3139 endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);3140 3141 if (CDecl->protocol_begin() != CDecl->protocol_end()) {3142 // advance to the end of the referenced protocols.3143 while (endHeader < cursor && *endHeader != '>') endHeader++;3144 endHeader++;3145 }3146 // rewrite the original header3147 ReplaceText(LocStart, endHeader-startBuf, Result);3148 } else {3149 // rewrite the original header *without* disturbing the '{'3150 ReplaceText(LocStart, cursor-startBuf, Result);3151 }3152 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {3153 Result = "\n struct ";3154 Result += RCDecl->getNameAsString();3155 Result += "_IMPL ";3156 Result += RCDecl->getNameAsString();3157 Result += "_IVARS;\n";3158 3159 // insert the super class structure definition.3160 SourceLocation OnePastCurly =3161 LocStart.getLocWithOffset(cursor-startBuf+1);3162 InsertText(OnePastCurly, Result);3163 }3164 cursor++; // past '{'3165 3166 // Now comment out any visibility specifiers.3167 while (cursor < endBuf) {3168 if (*cursor == '@') {3169 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);3170 // Skip whitespace.3171 for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)3172 /*scan*/;3173 3174 // FIXME: presence of @public, etc. inside comment results in3175 // this transformation as well, which is still correct c-code.3176 if (!strncmp(cursor, "public", strlen("public")) ||3177 !strncmp(cursor, "private", strlen("private")) ||3178 !strncmp(cursor, "package", strlen("package")) ||3179 !strncmp(cursor, "protected", strlen("protected")))3180 InsertText(atLoc, "// ");3181 }3182 // FIXME: If there are cases where '<' is used in ivar declaration part3183 // of user code, then scan the ivar list and use needToScanForQualifiers3184 // for type checking.3185 else if (*cursor == '<') {3186 SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf);3187 InsertText(atLoc, "/* ");3188 cursor = strchr(cursor, '>');3189 cursor++;3190 atLoc = LocStart.getLocWithOffset(cursor-startBuf);3191 InsertText(atLoc, " */");3192 } else if (*cursor == '^') { // rewrite block specifier.3193 SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf);3194 ReplaceText(caretLoc, 1, "*");3195 }3196 cursor++;3197 }3198 // Don't forget to add a ';'!!3199 InsertText(LocEnd.getLocWithOffset(1), ";");3200 } else { // we don't have any instance variables - insert super struct.3201 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3202 Result += " {\n struct ";3203 Result += RCDecl->getNameAsString();3204 Result += "_IMPL ";3205 Result += RCDecl->getNameAsString();3206 Result += "_IVARS;\n};\n";3207 ReplaceText(LocStart, endBuf-startBuf, Result);3208 }3209 // Mark this struct as having been generated.3210 if (!ObjCSynthesizedStructs.insert(CDecl).second)3211 llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct");3212}3213 3214//===----------------------------------------------------------------------===//3215// Meta Data Emission3216//===----------------------------------------------------------------------===//3217 3218/// RewriteImplementations - This routine rewrites all method implementations3219/// and emits meta-data.3220 3221void RewriteObjC::RewriteImplementations() {3222 int ClsDefCount = ClassImplementation.size();3223 int CatDefCount = CategoryImplementation.size();3224 3225 // Rewrite implemented methods3226 for (int i = 0; i < ClsDefCount; i++)3227 RewriteImplementationDecl(ClassImplementation[i]);3228 3229 for (int i = 0; i < CatDefCount; i++)3230 RewriteImplementationDecl(CategoryImplementation[i]);3231}3232 3233void RewriteObjC::RewriteByRefString(std::string &ResultStr,3234 const std::string &Name,3235 ValueDecl *VD, bool def) {3236 assert(BlockByRefDeclNo.count(VD) &&3237 "RewriteByRefString: ByRef decl missing");3238 if (def)3239 ResultStr += "struct ";3240 ResultStr += "__Block_byref_" + Name +3241 "_" + utostr(BlockByRefDeclNo[VD]) ;3242}3243 3244static bool HasLocalVariableExternalStorage(ValueDecl *VD) {3245 if (VarDecl *Var = dyn_cast<VarDecl>(VD))3246 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());3247 return false;3248}3249 3250std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,3251 StringRef funcName,3252 std::string Tag) {3253 const FunctionType *AFT = CE->getFunctionType();3254 QualType RT = AFT->getReturnType();3255 std::string StructRef = "struct " + Tag;3256 std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +3257 funcName.str() + "_" + "block_func_" + utostr(i);3258 3259 BlockDecl *BD = CE->getBlockDecl();3260 3261 if (isa<FunctionNoProtoType>(AFT)) {3262 // No user-supplied arguments. Still need to pass in a pointer to the3263 // block (to reference imported block decl refs).3264 S += "(" + StructRef + " *__cself)";3265 } else if (BD->param_empty()) {3266 S += "(" + StructRef + " *__cself)";3267 } else {3268 const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);3269 assert(FT && "SynthesizeBlockFunc: No function proto");3270 S += '(';3271 // first add the implicit argument.3272 S += StructRef + " *__cself, ";3273 std::string ParamStr;3274 for (BlockDecl::param_iterator AI = BD->param_begin(),3275 E = BD->param_end(); AI != E; ++AI) {3276 if (AI != BD->param_begin()) S += ", ";3277 ParamStr = (*AI)->getNameAsString();3278 QualType QT = (*AI)->getType();3279 (void)convertBlockPointerToFunctionPointer(QT);3280 QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());3281 S += ParamStr;3282 }3283 if (FT->isVariadic()) {3284 if (!BD->param_empty()) S += ", ";3285 S += "...";3286 }3287 S += ')';3288 }3289 S += " {\n";3290 3291 // Create local declarations to avoid rewriting all closure decl ref exprs.3292 // First, emit a declaration for all "by ref" decls.3293 for (auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;3294 ++I) {3295 S += " ";3296 std::string Name = (*I)->getNameAsString();3297 std::string TypeString;3298 RewriteByRefString(TypeString, Name, (*I));3299 TypeString += " *";3300 Name = TypeString + Name;3301 S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";3302 }3303 // Next, emit a declaration for all "by copy" declarations.3304 for (auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;3305 ++I) {3306 S += " ";3307 // Handle nested closure invocation. For example:3308 //3309 // void (^myImportedClosure)(void);3310 // myImportedClosure = ^(void) { setGlobalInt(x + y); };3311 //3312 // void (^anotherClosure)(void);3313 // anotherClosure = ^(void) {3314 // myImportedClosure(); // import and invoke the closure3315 // };3316 //3317 if (isTopLevelBlockPointerType((*I)->getType())) {3318 RewriteBlockPointerTypeVariable(S, (*I));3319 S += " = (";3320 RewriteBlockPointerType(S, (*I)->getType());3321 S += ")";3322 S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n";3323 }3324 else {3325 std::string Name = (*I)->getNameAsString();3326 QualType QT = (*I)->getType();3327 if (HasLocalVariableExternalStorage(*I))3328 QT = Context->getPointerType(QT);3329 QT.getAsStringInternal(Name, Context->getPrintingPolicy());3330 S += Name + " = __cself->" +3331 (*I)->getNameAsString() + "; // bound by copy\n";3332 }3333 }3334 std::string RewrittenStr = RewrittenBlockExprs[CE];3335 const char *cstr = RewrittenStr.c_str();3336 while (*cstr++ != '{') ;3337 S += cstr;3338 S += "\n";3339 return S;3340}3341 3342std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,3343 StringRef funcName,3344 std::string Tag) {3345 std::string StructRef = "struct " + Tag;3346 std::string S = "static void __";3347 3348 S += funcName;3349 S += "_block_copy_" + utostr(i);3350 S += "(" + StructRef;3351 S += "*dst, " + StructRef;3352 S += "*src) {";3353 for (ValueDecl *VD : ImportedBlockDecls) {3354 S += "_Block_object_assign((void*)&dst->";3355 S += VD->getNameAsString();3356 S += ", (void*)src->";3357 S += VD->getNameAsString();3358 if (BlockByRefDecls.contains(VD))3359 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";3360 else if (VD->getType()->isBlockPointerType())3361 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";3362 else3363 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";3364 }3365 S += "}\n";3366 3367 S += "\nstatic void __";3368 S += funcName;3369 S += "_block_dispose_" + utostr(i);3370 S += "(" + StructRef;3371 S += "*src) {";3372 for (ValueDecl *VD : ImportedBlockDecls) {3373 S += "_Block_object_dispose((void*)src->";3374 S += VD->getNameAsString();3375 if (BlockByRefDecls.contains(VD))3376 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";3377 else if (VD->getType()->isBlockPointerType())3378 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";3379 else3380 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";3381 }3382 S += "}\n";3383 return S;3384}3385 3386std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,3387 std::string Desc) {3388 std::string S = "\nstruct " + Tag;3389 std::string Constructor = " " + Tag;3390 3391 S += " {\n struct __block_impl impl;\n";3392 S += " struct " + Desc;3393 S += "* Desc;\n";3394 3395 Constructor += "(void *fp, "; // Invoke function pointer.3396 Constructor += "struct " + Desc; // Descriptor pointer.3397 Constructor += " *desc";3398 3399 if (BlockDeclRefs.size()) {3400 // Output all "by copy" declarations.3401 for (auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;3402 ++I) {3403 S += " ";3404 std::string FieldName = (*I)->getNameAsString();3405 std::string ArgName = "_" + FieldName;3406 // Handle nested closure invocation. For example:3407 //3408 // void (^myImportedBlock)(void);3409 // myImportedBlock = ^(void) { setGlobalInt(x + y); };3410 //3411 // void (^anotherBlock)(void);3412 // anotherBlock = ^(void) {3413 // myImportedBlock(); // import and invoke the closure3414 // };3415 //3416 if (isTopLevelBlockPointerType((*I)->getType())) {3417 S += "struct __block_impl *";3418 Constructor += ", void *" + ArgName;3419 } else {3420 QualType QT = (*I)->getType();3421 if (HasLocalVariableExternalStorage(*I))3422 QT = Context->getPointerType(QT);3423 QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());3424 QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());3425 Constructor += ", " + ArgName;3426 }3427 S += FieldName + ";\n";3428 }3429 // Output all "by ref" declarations.3430 for (auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;3431 ++I) {3432 S += " ";3433 std::string FieldName = (*I)->getNameAsString();3434 std::string ArgName = "_" + FieldName;3435 {3436 std::string TypeString;3437 RewriteByRefString(TypeString, FieldName, (*I));3438 TypeString += " *";3439 FieldName = TypeString + FieldName;3440 ArgName = TypeString + ArgName;3441 Constructor += ", " + ArgName;3442 }3443 S += FieldName + "; // by ref\n";3444 }3445 // Finish writing the constructor.3446 Constructor += ", int flags=0)";3447 // Initialize all "by copy" arguments.3448 bool firsTime = true;3449 for (auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;3450 ++I) {3451 std::string Name = (*I)->getNameAsString();3452 if (firsTime) {3453 Constructor += " : ";3454 firsTime = false;3455 }3456 else3457 Constructor += ", ";3458 if (isTopLevelBlockPointerType((*I)->getType()))3459 Constructor += Name + "((struct __block_impl *)_" + Name + ")";3460 else3461 Constructor += Name + "(_" + Name + ")";3462 }3463 // Initialize all "by ref" arguments.3464 for (auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;3465 ++I) {3466 std::string Name = (*I)->getNameAsString();3467 if (firsTime) {3468 Constructor += " : ";3469 firsTime = false;3470 }3471 else3472 Constructor += ", ";3473 Constructor += Name + "(_" + Name + "->__forwarding)";3474 }3475 3476 Constructor += " {\n";3477 if (GlobalVarDecl)3478 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";3479 else3480 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";3481 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";3482 3483 Constructor += " Desc = desc;\n";3484 } else {3485 // Finish writing the constructor.3486 Constructor += ", int flags=0) {\n";3487 if (GlobalVarDecl)3488 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";3489 else3490 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";3491 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";3492 Constructor += " Desc = desc;\n";3493 }3494 Constructor += " ";3495 Constructor += "}\n";3496 S += Constructor;3497 S += "};\n";3498 return S;3499}3500 3501std::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag,3502 std::string ImplTag, int i,3503 StringRef FunName,3504 unsigned hasCopy) {3505 std::string S = "\nstatic struct " + DescTag;3506 3507 S += " {\n unsigned long reserved;\n";3508 S += " unsigned long Block_size;\n";3509 if (hasCopy) {3510 S += " void (*copy)(struct ";3511 S += ImplTag; S += "*, struct ";3512 S += ImplTag; S += "*);\n";3513 3514 S += " void (*dispose)(struct ";3515 S += ImplTag; S += "*);\n";3516 }3517 S += "} ";3518 3519 S += DescTag + "_DATA = { 0, sizeof(struct ";3520 S += ImplTag + ")";3521 if (hasCopy) {3522 S += ", __" + FunName.str() + "_block_copy_" + utostr(i);3523 S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);3524 }3525 S += "};\n";3526 return S;3527}3528 3529void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,3530 StringRef FunName) {3531 // Insert declaration for the function in which block literal is used.3532 if (CurFunctionDeclToDeclareForBlock && !Blocks.empty())3533 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);3534 bool RewriteSC = (GlobalVarDecl &&3535 !Blocks.empty() &&3536 GlobalVarDecl->getStorageClass() == SC_Static &&3537 GlobalVarDecl->getType().getCVRQualifiers());3538 if (RewriteSC) {3539 std::string SC(" void __");3540 SC += GlobalVarDecl->getNameAsString();3541 SC += "() {}";3542 InsertText(FunLocStart, SC);3543 }3544 3545 // Insert closures that were part of the function.3546 for (unsigned i = 0, count=0; i < Blocks.size(); i++) {3547 CollectBlockDeclRefInfo(Blocks[i]);3548 // Need to copy-in the inner copied-in variables not actually used in this3549 // block.3550 for (int j = 0; j < InnerDeclRefsCount[i]; j++) {3551 DeclRefExpr *Exp = InnerDeclRefs[count++];3552 ValueDecl *VD = Exp->getDecl();3553 BlockDeclRefs.push_back(Exp);3554 if (VD->hasAttr<BlocksAttr>())3555 BlockByRefDecls.insert(VD);3556 else3557 BlockByCopyDecls.insert(VD);3558 // imported objects in the inner blocks not used in the outer3559 // blocks must be copied/disposed in the outer block as well.3560 if (VD->hasAttr<BlocksAttr>() ||3561 VD->getType()->isObjCObjectPointerType() ||3562 VD->getType()->isBlockPointerType())3563 ImportedBlockDecls.insert(VD);3564 }3565 3566 std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);3567 std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);3568 3569 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);3570 3571 InsertText(FunLocStart, CI);3572 3573 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);3574 3575 InsertText(FunLocStart, CF);3576 3577 if (ImportedBlockDecls.size()) {3578 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);3579 InsertText(FunLocStart, HF);3580 }3581 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,3582 ImportedBlockDecls.size() > 0);3583 InsertText(FunLocStart, BD);3584 3585 BlockDeclRefs.clear();3586 BlockByRefDecls.clear();3587 BlockByCopyDecls.clear();3588 ImportedBlockDecls.clear();3589 }3590 if (RewriteSC) {3591 // Must insert any 'const/volatile/static here. Since it has been3592 // removed as result of rewriting of block literals.3593 std::string SC;3594 if (GlobalVarDecl->getStorageClass() == SC_Static)3595 SC = "static ";3596 if (GlobalVarDecl->getType().isConstQualified())3597 SC += "const ";3598 if (GlobalVarDecl->getType().isVolatileQualified())3599 SC += "volatile ";3600 if (GlobalVarDecl->getType().isRestrictQualified())3601 SC += "restrict ";3602 InsertText(FunLocStart, SC);3603 }3604 3605 Blocks.clear();3606 InnerDeclRefsCount.clear();3607 InnerDeclRefs.clear();3608 RewrittenBlockExprs.clear();3609}3610 3611void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {3612 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();3613 StringRef FuncName = FD->getName();3614 3615 SynthesizeBlockLiterals(FunLocStart, FuncName);3616}3617 3618static void BuildUniqueMethodName(std::string &Name,3619 ObjCMethodDecl *MD) {3620 ObjCInterfaceDecl *IFace = MD->getClassInterface();3621 Name = std::string(IFace->getName());3622 Name += "__" + MD->getSelector().getAsString();3623 // Convert colons to underscores.3624 std::string::size_type loc = 0;3625 while ((loc = Name.find(':', loc)) != std::string::npos)3626 Name.replace(loc, 1, "_");3627}3628 3629void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {3630 // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");3631 // SourceLocation FunLocStart = MD->getBeginLoc();3632 SourceLocation FunLocStart = MD->getBeginLoc();3633 std::string FuncName;3634 BuildUniqueMethodName(FuncName, MD);3635 SynthesizeBlockLiterals(FunLocStart, FuncName);3636}3637 3638void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) {3639 for (Stmt *SubStmt : S->children())3640 if (SubStmt) {3641 if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))3642 GetBlockDeclRefExprs(CBE->getBody());3643 else3644 GetBlockDeclRefExprs(SubStmt);3645 }3646 // Handle specific things.3647 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))3648 if (DRE->refersToEnclosingVariableOrCapture() ||3649 HasLocalVariableExternalStorage(DRE->getDecl()))3650 // FIXME: Handle enums.3651 BlockDeclRefs.push_back(DRE);3652}3653 3654void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S,3655 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,3656 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {3657 for (Stmt *SubStmt : S->children())3658 if (SubStmt) {3659 if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {3660 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));3661 GetInnerBlockDeclRefExprs(CBE->getBody(),3662 InnerBlockDeclRefs,3663 InnerContexts);3664 }3665 else3666 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);3667 }3668 // Handle specific things.3669 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {3670 if (DRE->refersToEnclosingVariableOrCapture() ||3671 HasLocalVariableExternalStorage(DRE->getDecl())) {3672 if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))3673 InnerBlockDeclRefs.push_back(DRE);3674 if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))3675 if (Var->isFunctionOrMethodVarDecl())3676 ImportedLocalExternalDecls.insert(Var);3677 }3678 }3679}3680 3681/// convertFunctionTypeOfBlocks - This routine converts a function type3682/// whose result type may be a block pointer or whose argument type(s)3683/// might be block pointers to an equivalent function type replacing3684/// all block pointers to function pointers.3685QualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {3686 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);3687 // FTP will be null for closures that don't take arguments.3688 // Generate a funky cast.3689 SmallVector<QualType, 8> ArgTypes;3690 QualType Res = FT->getReturnType();3691 bool HasBlockType = convertBlockPointerToFunctionPointer(Res);3692 3693 if (FTP) {3694 for (auto &I : FTP->param_types()) {3695 QualType t = I;3696 // Make sure we convert "t (^)(...)" to "t (*)(...)".3697 if (convertBlockPointerToFunctionPointer(t))3698 HasBlockType = true;3699 ArgTypes.push_back(t);3700 }3701 }3702 QualType FuncType;3703 // FIXME. Does this work if block takes no argument but has a return type3704 // which is of block type?3705 if (HasBlockType)3706 FuncType = getSimpleFunctionType(Res, ArgTypes);3707 else FuncType = QualType(FT, 0);3708 return FuncType;3709}3710 3711Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {3712 // Navigate to relevant type information.3713 const BlockPointerType *CPT = nullptr;3714 3715 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {3716 CPT = DRE->getType()->getAs<BlockPointerType>();3717 } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {3718 CPT = MExpr->getType()->getAs<BlockPointerType>();3719 }3720 else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {3721 return SynthesizeBlockCall(Exp, PRE->getSubExpr());3722 }3723 else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))3724 CPT = IEXPR->getType()->getAs<BlockPointerType>();3725 else if (const ConditionalOperator *CEXPR =3726 dyn_cast<ConditionalOperator>(BlockExp)) {3727 Expr *LHSExp = CEXPR->getLHS();3728 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);3729 Expr *RHSExp = CEXPR->getRHS();3730 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);3731 Expr *CONDExp = CEXPR->getCond();3732 ConditionalOperator *CondExpr = new (Context) ConditionalOperator(3733 CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),3734 cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);3735 return CondExpr;3736 } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {3737 CPT = IRE->getType()->getAs<BlockPointerType>();3738 } else if (const PseudoObjectExpr *POE3739 = dyn_cast<PseudoObjectExpr>(BlockExp)) {3740 CPT = POE->getType()->castAs<BlockPointerType>();3741 } else {3742 assert(false && "RewriteBlockClass: Bad type");3743 }3744 assert(CPT && "RewriteBlockClass: Bad type");3745 const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();3746 assert(FT && "RewriteBlockClass: Bad type");3747 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);3748 // FTP will be null for closures that don't take arguments.3749 3750 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,3751 SourceLocation(), SourceLocation(),3752 &Context->Idents.get("__block_impl"));3753 QualType PtrBlock = Context->getPointerType(Context->getCanonicalTagType(RD));3754 3755 // Generate a funky cast.3756 SmallVector<QualType, 8> ArgTypes;3757 3758 // Push the block argument type.3759 ArgTypes.push_back(PtrBlock);3760 if (FTP) {3761 for (auto &I : FTP->param_types()) {3762 QualType t = I;3763 // Make sure we convert "t (^)(...)" to "t (*)(...)".3764 if (!convertBlockPointerToFunctionPointer(t))3765 convertToUnqualifiedObjCType(t);3766 ArgTypes.push_back(t);3767 }3768 }3769 // Now do the pointer to function cast.3770 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);3771 3772 PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);3773 3774 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,3775 CK_BitCast,3776 const_cast<Expr*>(BlockExp));3777 // Don't forget the parens to enforce the proper binding.3778 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),3779 BlkCast);3780 //PE->dump();3781 3782 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),3783 SourceLocation(),3784 &Context->Idents.get("FuncPtr"),3785 Context->VoidPtrTy, nullptr,3786 /*BitWidth=*/nullptr, /*Mutable=*/true,3787 ICIS_NoInit);3788 MemberExpr *ME = MemberExpr::CreateImplicit(3789 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);3790 3791 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,3792 CK_BitCast, ME);3793 PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);3794 3795 SmallVector<Expr*, 8> BlkExprs;3796 // Add the implicit argument.3797 BlkExprs.push_back(BlkCast);3798 // Add the user arguments.3799 for (CallExpr::arg_iterator I = Exp->arg_begin(),3800 E = Exp->arg_end(); I != E; ++I) {3801 BlkExprs.push_back(*I);3802 }3803 CallExpr *CE =3804 CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,3805 SourceLocation(), FPOptionsOverride());3806 return CE;3807}3808 3809// We need to return the rewritten expression to handle cases where the3810// BlockDeclRefExpr is embedded in another expression being rewritten.3811// For example:3812//3813// int main() {3814// __block Foo *f;3815// __block int i;3816//3817// void (^myblock)() = ^() {3818// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten).3819// i = 77;3820// };3821//}3822Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {3823 // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR3824 // for each DeclRefExp where BYREFVAR is name of the variable.3825 ValueDecl *VD = DeclRefExp->getDecl();3826 bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||3827 HasLocalVariableExternalStorage(DeclRefExp->getDecl());3828 3829 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),3830 SourceLocation(),3831 &Context->Idents.get("__forwarding"),3832 Context->VoidPtrTy, nullptr,3833 /*BitWidth=*/nullptr, /*Mutable=*/true,3834 ICIS_NoInit);3835 MemberExpr *ME =3836 MemberExpr::CreateImplicit(*Context, DeclRefExp, isArrow, FD,3837 FD->getType(), VK_LValue, OK_Ordinary);3838 3839 StringRef Name = VD->getName();3840 FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),3841 &Context->Idents.get(Name),3842 Context->VoidPtrTy, nullptr,3843 /*BitWidth=*/nullptr, /*Mutable=*/true,3844 ICIS_NoInit);3845 ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),3846 VK_LValue, OK_Ordinary);3847 3848 // Need parens to enforce precedence.3849 ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),3850 DeclRefExp->getExprLoc(),3851 ME);3852 ReplaceStmt(DeclRefExp, PE);3853 return PE;3854}3855 3856// Rewrites the imported local variable V with external storage3857// (static, extern, etc.) as *V3858//3859Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {3860 ValueDecl *VD = DRE->getDecl();3861 if (VarDecl *Var = dyn_cast<VarDecl>(VD))3862 if (!ImportedLocalExternalDecls.count(Var))3863 return DRE;3864 Expr *Exp = UnaryOperator::Create(3865 const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),3866 VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());3867 // Need parens to enforce precedence.3868 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),3869 Exp);3870 ReplaceStmt(DRE, PE);3871 return PE;3872}3873 3874void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {3875 SourceLocation LocStart = CE->getLParenLoc();3876 SourceLocation LocEnd = CE->getRParenLoc();3877 3878 // Need to avoid trying to rewrite synthesized casts.3879 if (LocStart.isInvalid())3880 return;3881 // Need to avoid trying to rewrite casts contained in macros.3882 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))3883 return;3884 3885 const char *startBuf = SM->getCharacterData(LocStart);3886 const char *endBuf = SM->getCharacterData(LocEnd);3887 QualType QT = CE->getType();3888 const Type* TypePtr = QT->getAs<Type>();3889 if (isa<TypeOfExprType>(TypePtr)) {3890 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);3891 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();3892 std::string TypeAsString = "(";3893 RewriteBlockPointerType(TypeAsString, QT);3894 TypeAsString += ")";3895 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);3896 return;3897 }3898 // advance the location to startArgList.3899 const char *argPtr = startBuf;3900 3901 while (*argPtr++ && (argPtr < endBuf)) {3902 switch (*argPtr) {3903 case '^':3904 // Replace the '^' with '*'.3905 LocStart = LocStart.getLocWithOffset(argPtr-startBuf);3906 ReplaceText(LocStart, 1, "*");3907 break;3908 }3909 }3910}3911 3912void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {3913 SourceLocation DeclLoc = FD->getLocation();3914 unsigned parenCount = 0;3915 3916 // We have 1 or more arguments that have closure pointers.3917 const char *startBuf = SM->getCharacterData(DeclLoc);3918 const char *startArgList = strchr(startBuf, '(');3919 3920 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");3921 3922 parenCount++;3923 // advance the location to startArgList.3924 DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);3925 assert((DeclLoc.isValid()) && "Invalid DeclLoc");3926 3927 const char *argPtr = startArgList;3928 3929 while (*argPtr++ && parenCount) {3930 switch (*argPtr) {3931 case '^':3932 // Replace the '^' with '*'.3933 DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);3934 ReplaceText(DeclLoc, 1, "*");3935 break;3936 case '(':3937 parenCount++;3938 break;3939 case ')':3940 parenCount--;3941 break;3942 }3943 }3944}3945 3946bool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {3947 const FunctionProtoType *FTP;3948 const PointerType *PT = QT->getAs<PointerType>();3949 if (PT) {3950 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();3951 } else {3952 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();3953 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");3954 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();3955 }3956 if (FTP) {3957 for (const auto &I : FTP->param_types())3958 if (isTopLevelBlockPointerType(I))3959 return true;3960 }3961 return false;3962}3963 3964bool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {3965 const FunctionProtoType *FTP;3966 const PointerType *PT = QT->getAs<PointerType>();3967 if (PT) {3968 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();3969 } else {3970 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();3971 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");3972 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();3973 }3974 if (FTP) {3975 for (const auto &I : FTP->param_types()) {3976 if (I->isObjCQualifiedIdType())3977 return true;3978 if (I->isObjCObjectPointerType() &&3979 I->getPointeeType()->isObjCQualifiedInterfaceType())3980 return true;3981 }3982 3983 }3984 return false;3985}3986 3987void RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen,3988 const char *&RParen) {3989 const char *argPtr = strchr(Name, '(');3990 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");3991 3992 LParen = argPtr; // output the start.3993 argPtr++; // skip past the left paren.3994 unsigned parenCount = 1;3995 3996 while (*argPtr && parenCount) {3997 switch (*argPtr) {3998 case '(': parenCount++; break;3999 case ')': parenCount--; break;4000 default: break;4001 }4002 if (parenCount) argPtr++;4003 }4004 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");4005 RParen = argPtr; // output the end4006}4007 4008void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {4009 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {4010 RewriteBlockPointerFunctionArgs(FD);4011 return;4012 }4013 // Handle Variables and Typedefs.4014 SourceLocation DeclLoc = ND->getLocation();4015 QualType DeclT;4016 if (VarDecl *VD = dyn_cast<VarDecl>(ND))4017 DeclT = VD->getType();4018 else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))4019 DeclT = TDD->getUnderlyingType();4020 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))4021 DeclT = FD->getType();4022 else4023 llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");4024 4025 const char *startBuf = SM->getCharacterData(DeclLoc);4026 const char *endBuf = startBuf;4027 // scan backward (from the decl location) for the end of the previous decl.4028 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)4029 startBuf--;4030 SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);4031 std::string buf;4032 unsigned OrigLength=0;4033 // *startBuf != '^' if we are dealing with a pointer to function that4034 // may take block argument types (which will be handled below).4035 if (*startBuf == '^') {4036 // Replace the '^' with '*', computing a negative offset.4037 buf = '*';4038 startBuf++;4039 OrigLength++;4040 }4041 while (*startBuf != ')') {4042 buf += *startBuf;4043 startBuf++;4044 OrigLength++;4045 }4046 buf += ')';4047 OrigLength++;4048 4049 if (PointerTypeTakesAnyBlockArguments(DeclT) ||4050 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {4051 // Replace the '^' with '*' for arguments.4052 // Replace id<P> with id/*<>*/4053 DeclLoc = ND->getLocation();4054 startBuf = SM->getCharacterData(DeclLoc);4055 const char *argListBegin, *argListEnd;4056 GetExtentOfArgList(startBuf, argListBegin, argListEnd);4057 while (argListBegin < argListEnd) {4058 if (*argListBegin == '^')4059 buf += '*';4060 else if (*argListBegin == '<') {4061 buf += "/*";4062 buf += *argListBegin++;4063 OrigLength++;4064 while (*argListBegin != '>') {4065 buf += *argListBegin++;4066 OrigLength++;4067 }4068 buf += *argListBegin;4069 buf += "*/";4070 }4071 else4072 buf += *argListBegin;4073 argListBegin++;4074 OrigLength++;4075 }4076 buf += ')';4077 OrigLength++;4078 }4079 ReplaceText(Start, OrigLength, buf);4080}4081 4082/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:4083/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,4084/// struct Block_byref_id_object *src) {4085/// _Block_object_assign (&_dest->object, _src->object,4086/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4087/// [|BLOCK_FIELD_IS_WEAK]) // object4088/// _Block_object_assign(&_dest->object, _src->object,4089/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4090/// [|BLOCK_FIELD_IS_WEAK]) // block4091/// }4092/// And:4093/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {4094/// _Block_object_dispose(_src->object,4095/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4096/// [|BLOCK_FIELD_IS_WEAK]) // object4097/// _Block_object_dispose(_src->object,4098/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4099/// [|BLOCK_FIELD_IS_WEAK]) // block4100/// }4101 4102std::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,4103 int flag) {4104 std::string S;4105 if (!CopyDestroyCache.insert(flag).second)4106 return S;4107 S = "static void __Block_byref_id_object_copy_";4108 S += utostr(flag);4109 S += "(void *dst, void *src) {\n";4110 4111 // offset into the object pointer is computed as:4112 // void * + void* + int + int + void* + void *4113 unsigned IntSize =4114 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));4115 unsigned VoidPtrSize =4116 static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));4117 4118 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();4119 S += " _Block_object_assign((char*)dst + ";4120 S += utostr(offset);4121 S += ", *(void * *) ((char*)src + ";4122 S += utostr(offset);4123 S += "), ";4124 S += utostr(flag);4125 S += ");\n}\n";4126 4127 S += "static void __Block_byref_id_object_dispose_";4128 S += utostr(flag);4129 S += "(void *src) {\n";4130 S += " _Block_object_dispose(*(void * *) ((char*)src + ";4131 S += utostr(offset);4132 S += "), ";4133 S += utostr(flag);4134 S += ");\n}\n";4135 return S;4136}4137 4138/// RewriteByRefVar - For each __block typex ND variable this routine transforms4139/// the declaration into:4140/// struct __Block_byref_ND {4141/// void *__isa; // NULL for everything except __weak pointers4142/// struct __Block_byref_ND *__forwarding;4143/// int32_t __flags;4144/// int32_t __size;4145/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object4146/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object4147/// typex ND;4148/// };4149///4150/// It then replaces declaration of ND variable with:4151/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,4152/// __size=sizeof(struct __Block_byref_ND),4153/// ND=initializer-if-any};4154///4155///4156void RewriteObjC::RewriteByRefVar(VarDecl *ND) {4157 // Insert declaration for the function in which block literal is4158 // used.4159 if (CurFunctionDeclToDeclareForBlock)4160 RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock);4161 int flag = 0;4162 int isa = 0;4163 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();4164 if (DeclLoc.isInvalid())4165 // If type location is missing, it is because of missing type (a warning).4166 // Use variable's location which is good for this case.4167 DeclLoc = ND->getLocation();4168 const char *startBuf = SM->getCharacterData(DeclLoc);4169 SourceLocation X = ND->getEndLoc();4170 X = SM->getExpansionLoc(X);4171 const char *endBuf = SM->getCharacterData(X);4172 std::string Name(ND->getNameAsString());4173 std::string ByrefType;4174 RewriteByRefString(ByrefType, Name, ND, true);4175 ByrefType += " {\n";4176 ByrefType += " void *__isa;\n";4177 RewriteByRefString(ByrefType, Name, ND);4178 ByrefType += " *__forwarding;\n";4179 ByrefType += " int __flags;\n";4180 ByrefType += " int __size;\n";4181 // Add void *__Block_byref_id_object_copy;4182 // void *__Block_byref_id_object_dispose; if needed.4183 QualType Ty = ND->getType();4184 bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);4185 if (HasCopyAndDispose) {4186 ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";4187 ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";4188 }4189 4190 QualType T = Ty;4191 (void)convertBlockPointerToFunctionPointer(T);4192 T.getAsStringInternal(Name, Context->getPrintingPolicy());4193 4194 ByrefType += " " + Name + ";\n";4195 ByrefType += "};\n";4196 // Insert this type in global scope. It is needed by helper function.4197 SourceLocation FunLocStart;4198 if (CurFunctionDef)4199 FunLocStart = CurFunctionDef->getTypeSpecStartLoc();4200 else {4201 assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");4202 FunLocStart = CurMethodDef->getBeginLoc();4203 }4204 InsertText(FunLocStart, ByrefType);4205 if (Ty.isObjCGCWeak()) {4206 flag |= BLOCK_FIELD_IS_WEAK;4207 isa = 1;4208 }4209 4210 if (HasCopyAndDispose) {4211 flag = BLOCK_BYREF_CALLER;4212 QualType Ty = ND->getType();4213 // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.4214 if (Ty->isBlockPointerType())4215 flag |= BLOCK_FIELD_IS_BLOCK;4216 else4217 flag |= BLOCK_FIELD_IS_OBJECT;4218 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);4219 if (!HF.empty())4220 InsertText(FunLocStart, HF);4221 }4222 4223 // struct __Block_byref_ND ND =4224 // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),4225 // initializer-if-any};4226 bool hasInit = (ND->getInit() != nullptr);4227 unsigned flags = 0;4228 if (HasCopyAndDispose)4229 flags |= BLOCK_HAS_COPY_DISPOSE;4230 Name = ND->getNameAsString();4231 ByrefType.clear();4232 RewriteByRefString(ByrefType, Name, ND);4233 std::string ForwardingCastType("(");4234 ForwardingCastType += ByrefType + " *)";4235 if (!hasInit) {4236 ByrefType += " " + Name + " = {(void*)";4237 ByrefType += utostr(isa);4238 ByrefType += "," + ForwardingCastType + "&" + Name + ", ";4239 ByrefType += utostr(flags);4240 ByrefType += ", ";4241 ByrefType += "sizeof(";4242 RewriteByRefString(ByrefType, Name, ND);4243 ByrefType += ")";4244 if (HasCopyAndDispose) {4245 ByrefType += ", __Block_byref_id_object_copy_";4246 ByrefType += utostr(flag);4247 ByrefType += ", __Block_byref_id_object_dispose_";4248 ByrefType += utostr(flag);4249 }4250 ByrefType += "};\n";4251 unsigned nameSize = Name.size();4252 // for block or function pointer declaration. Name is already4253 // part of the declaration.4254 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())4255 nameSize = 1;4256 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);4257 }4258 else {4259 SourceLocation startLoc;4260 Expr *E = ND->getInit();4261 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))4262 startLoc = ECE->getLParenLoc();4263 else4264 startLoc = E->getBeginLoc();4265 startLoc = SM->getExpansionLoc(startLoc);4266 endBuf = SM->getCharacterData(startLoc);4267 ByrefType += " " + Name;4268 ByrefType += " = {(void*)";4269 ByrefType += utostr(isa);4270 ByrefType += "," + ForwardingCastType + "&" + Name + ", ";4271 ByrefType += utostr(flags);4272 ByrefType += ", ";4273 ByrefType += "sizeof(";4274 RewriteByRefString(ByrefType, Name, ND);4275 ByrefType += "), ";4276 if (HasCopyAndDispose) {4277 ByrefType += "__Block_byref_id_object_copy_";4278 ByrefType += utostr(flag);4279 ByrefType += ", __Block_byref_id_object_dispose_";4280 ByrefType += utostr(flag);4281 ByrefType += ", ";4282 }4283 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);4284 4285 // Complete the newly synthesized compound expression by inserting a right4286 // curly brace before the end of the declaration.4287 // FIXME: This approach avoids rewriting the initializer expression. It4288 // also assumes there is only one declarator. For example, the following4289 // isn't currently supported by this routine (in general):4290 //4291 // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37;4292 //4293 const char *startInitializerBuf = SM->getCharacterData(startLoc);4294 const char *semiBuf = strchr(startInitializerBuf, ';');4295 assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'");4296 SourceLocation semiLoc =4297 startLoc.getLocWithOffset(semiBuf-startInitializerBuf);4298 4299 InsertText(semiLoc, "}");4300 }4301}4302 4303void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {4304 // Add initializers for any closure decl refs.4305 GetBlockDeclRefExprs(Exp->getBody());4306 if (BlockDeclRefs.size()) {4307 // Unique all "by copy" declarations.4308 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)4309 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())4310 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());4311 // Unique all "by ref" declarations.4312 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)4313 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())4314 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());4315 // Find any imported blocks...they will need special attention.4316 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)4317 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||4318 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||4319 BlockDeclRefs[i]->getType()->isBlockPointerType())4320 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());4321 }4322}4323 4324FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) {4325 IdentifierInfo *ID = &Context->Idents.get(name);4326 QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);4327 return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),4328 SourceLocation(), ID, FType, nullptr, SC_Extern,4329 false, false);4330}4331 4332Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp,4333 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {4334 const BlockDecl *block = Exp->getBlockDecl();4335 Blocks.push_back(Exp);4336 4337 CollectBlockDeclRefInfo(Exp);4338 4339 // Add inner imported variables now used in current block.4340 int countOfInnerDecls = 0;4341 if (!InnerBlockDeclRefs.empty()) {4342 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {4343 DeclRefExpr *Exp = InnerBlockDeclRefs[i];4344 ValueDecl *VD = Exp->getDecl();4345 if (!VD->hasAttr<BlocksAttr>() && BlockByCopyDecls.insert(VD)) {4346 // We need to save the copied-in variables in nested4347 // blocks because it is needed at the end for some of the API4348 // generations. See SynthesizeBlockLiterals routine.4349 InnerDeclRefs.push_back(Exp);4350 countOfInnerDecls++;4351 BlockDeclRefs.push_back(Exp);4352 }4353 if (VD->hasAttr<BlocksAttr>() && BlockByRefDecls.insert(VD)) {4354 InnerDeclRefs.push_back(Exp);4355 countOfInnerDecls++;4356 BlockDeclRefs.push_back(Exp);4357 }4358 }4359 // Find any imported blocks...they will need special attention.4360 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)4361 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||4362 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||4363 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())4364 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());4365 }4366 InnerDeclRefsCount.push_back(countOfInnerDecls);4367 4368 std::string FuncName;4369 4370 if (CurFunctionDef)4371 FuncName = CurFunctionDef->getNameAsString();4372 else if (CurMethodDef)4373 BuildUniqueMethodName(FuncName, CurMethodDef);4374 else if (GlobalVarDecl)4375 FuncName = std::string(GlobalVarDecl->getNameAsString());4376 4377 std::string BlockNumber = utostr(Blocks.size()-1);4378 4379 std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber;4380 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;4381 4382 // Get a pointer to the function type so we can cast appropriately.4383 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());4384 QualType FType = Context->getPointerType(BFT);4385 4386 FunctionDecl *FD;4387 Expr *NewRep;4388 4389 // Simulate a constructor call...4390 FD = SynthBlockInitFunctionDecl(Tag);4391 DeclRefExpr *DRE = new (Context)4392 DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());4393 4394 SmallVector<Expr*, 4> InitExprs;4395 4396 // Initialize the block function.4397 FD = SynthBlockInitFunctionDecl(Func);4398 DeclRefExpr *Arg = new (Context) DeclRefExpr(4399 *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());4400 CastExpr *castExpr =4401 NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg);4402 InitExprs.push_back(castExpr);4403 4404 // Initialize the block descriptor.4405 std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";4406 4407 VarDecl *NewVD = VarDecl::Create(4408 *Context, TUDecl, SourceLocation(), SourceLocation(),4409 &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);4410 UnaryOperator *DescRefExpr = UnaryOperator::Create(4411 const_cast<ASTContext &>(*Context),4412 new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,4413 VK_LValue, SourceLocation()),4414 UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,4415 OK_Ordinary, SourceLocation(), false, FPOptionsOverride());4416 InitExprs.push_back(DescRefExpr);4417 4418 // Add initializers for any closure decl refs.4419 if (BlockDeclRefs.size()) {4420 Expr *Exp;4421 // Output all "by copy" declarations.4422 for (auto I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E;4423 ++I) {4424 if (isObjCType((*I)->getType())) {4425 // FIXME: Conform to ABI ([[obj retain] autorelease]).4426 FD = SynthBlockInitFunctionDecl((*I)->getName());4427 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),4428 VK_LValue, SourceLocation());4429 if (HasLocalVariableExternalStorage(*I)) {4430 QualType QT = (*I)->getType();4431 QT = Context->getPointerType(QT);4432 Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,4433 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,4434 SourceLocation(), false,4435 FPOptionsOverride());4436 }4437 } else if (isTopLevelBlockPointerType((*I)->getType())) {4438 FD = SynthBlockInitFunctionDecl((*I)->getName());4439 Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),4440 VK_LValue, SourceLocation());4441 Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast,4442 Arg);4443 } else {4444 FD = SynthBlockInitFunctionDecl((*I)->getName());4445 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),4446 VK_LValue, SourceLocation());4447 if (HasLocalVariableExternalStorage(*I)) {4448 QualType QT = (*I)->getType();4449 QT = Context->getPointerType(QT);4450 Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,4451 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,4452 SourceLocation(), false,4453 FPOptionsOverride());4454 }4455 }4456 InitExprs.push_back(Exp);4457 }4458 // Output all "by ref" declarations.4459 for (auto I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E;4460 ++I) {4461 ValueDecl *ND = (*I);4462 std::string Name(ND->getNameAsString());4463 std::string RecName;4464 RewriteByRefString(RecName, Name, ND, true);4465 IdentifierInfo *II = &Context->Idents.get(RecName.c_str()4466 + sizeof("struct"));4467 RecordDecl *RD =4468 RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,4469 SourceLocation(), SourceLocation(), II);4470 assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");4471 QualType castT =4472 Context->getPointerType(Context->getCanonicalTagType(RD));4473 4474 FD = SynthBlockInitFunctionDecl((*I)->getName());4475 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),4476 VK_LValue, SourceLocation());4477 bool isNestedCapturedVar = false;4478 if (block)4479 for (const auto &CI : block->captures()) {4480 const VarDecl *variable = CI.getVariable();4481 if (variable == ND && CI.isNested()) {4482 assert (CI.isByRef() &&4483 "SynthBlockInitExpr - captured block variable is not byref");4484 isNestedCapturedVar = true;4485 break;4486 }4487 }4488 // captured nested byref variable has its address passed. Do not take4489 // its address again.4490 if (!isNestedCapturedVar)4491 Exp = UnaryOperator::Create(4492 const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,4493 Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,4494 SourceLocation(), false, FPOptionsOverride());4495 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);4496 InitExprs.push_back(Exp);4497 }4498 }4499 if (ImportedBlockDecls.size()) {4500 // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR4501 int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);4502 unsigned IntSize =4503 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));4504 Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),4505 Context->IntTy, SourceLocation());4506 InitExprs.push_back(FlagExp);4507 }4508 NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,4509 SourceLocation(), FPOptionsOverride());4510 NewRep = UnaryOperator::Create(4511 const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,4512 Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,4513 SourceLocation(), false, FPOptionsOverride());4514 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,4515 NewRep);4516 BlockDeclRefs.clear();4517 BlockByRefDecls.clear();4518 BlockByCopyDecls.clear();4519 ImportedBlockDecls.clear();4520 return NewRep;4521}4522 4523bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {4524 if (const ObjCForCollectionStmt * CS =4525 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))4526 return CS->getElement() == DS;4527 return false;4528}4529 4530//===----------------------------------------------------------------------===//4531// Function Body / Expression rewriting4532//===----------------------------------------------------------------------===//4533 4534Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {4535 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||4536 isa<DoStmt>(S) || isa<ForStmt>(S))4537 Stmts.push_back(S);4538 else if (isa<ObjCForCollectionStmt>(S)) {4539 Stmts.push_back(S);4540 ObjCBcLabelNo.push_back(++BcLabelCount);4541 }4542 4543 // Pseudo-object operations and ivar references need special4544 // treatment because we're going to recursively rewrite them.4545 if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {4546 if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {4547 return RewritePropertyOrImplicitSetter(PseudoOp);4548 } else {4549 return RewritePropertyOrImplicitGetter(PseudoOp);4550 }4551 } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {4552 return RewriteObjCIvarRefExpr(IvarRefExpr);4553 }4554 4555 SourceRange OrigStmtRange = S->getSourceRange();4556 4557 // Perform a bottom up rewrite of all children.4558 for (Stmt *&childStmt : S->children())4559 if (childStmt) {4560 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);4561 if (newStmt) {4562 childStmt = newStmt;4563 }4564 }4565 4566 if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {4567 SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;4568 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;4569 InnerContexts.insert(BE->getBlockDecl());4570 ImportedLocalExternalDecls.clear();4571 GetInnerBlockDeclRefExprs(BE->getBody(),4572 InnerBlockDeclRefs, InnerContexts);4573 // Rewrite the block body in place.4574 Stmt *SaveCurrentBody = CurrentBody;4575 CurrentBody = BE->getBody();4576 PropParentMap = nullptr;4577 // block literal on rhs of a property-dot-sytax assignment4578 // must be replaced by its synthesize ast so getRewrittenText4579 // works as expected. In this case, what actually ends up on RHS4580 // is the blockTranscribed which is the helper function for the4581 // block literal; as in: self.c = ^() {[ace ARR];};4582 bool saveDisableReplaceStmt = DisableReplaceStmt;4583 DisableReplaceStmt = false;4584 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());4585 DisableReplaceStmt = saveDisableReplaceStmt;4586 CurrentBody = SaveCurrentBody;4587 PropParentMap = nullptr;4588 ImportedLocalExternalDecls.clear();4589 // Now we snarf the rewritten text and stash it away for later use.4590 std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());4591 RewrittenBlockExprs[BE] = Str;4592 4593 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);4594 4595 //blockTranscribed->dump();4596 ReplaceStmt(S, blockTranscribed);4597 return blockTranscribed;4598 }4599 // Handle specific things.4600 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))4601 return RewriteAtEncode(AtEncode);4602 4603 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))4604 return RewriteAtSelector(AtSelector);4605 4606 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))4607 return RewriteObjCStringLiteral(AtString);4608 4609 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {4610#if 04611 // Before we rewrite it, put the original message expression in a comment.4612 SourceLocation startLoc = MessExpr->getBeginLoc();4613 SourceLocation endLoc = MessExpr->getEndLoc();4614 4615 const char *startBuf = SM->getCharacterData(startLoc);4616 const char *endBuf = SM->getCharacterData(endLoc);4617 4618 std::string messString;4619 messString += "// ";4620 messString.append(startBuf, endBuf-startBuf+1);4621 messString += "\n";4622 4623 // FIXME: Missing definition of4624 // InsertText(clang::SourceLocation, char const*, unsigned int).4625 // InsertText(startLoc, messString);4626 // Tried this, but it didn't work either...4627 // ReplaceText(startLoc, 0, messString.c_str(), messString.size());4628#endif4629 return RewriteMessageExpr(MessExpr);4630 }4631 4632 if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))4633 return RewriteObjCTryStmt(StmtTry);4634 4635 if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))4636 return RewriteObjCSynchronizedStmt(StmtTry);4637 4638 if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))4639 return RewriteObjCThrowStmt(StmtThrow);4640 4641 if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))4642 return RewriteObjCProtocolExpr(ProtocolExp);4643 4644 if (ObjCForCollectionStmt *StmtForCollection =4645 dyn_cast<ObjCForCollectionStmt>(S))4646 return RewriteObjCForCollectionStmt(StmtForCollection,4647 OrigStmtRange.getEnd());4648 if (BreakStmt *StmtBreakStmt =4649 dyn_cast<BreakStmt>(S))4650 return RewriteBreakStmt(StmtBreakStmt);4651 if (ContinueStmt *StmtContinueStmt =4652 dyn_cast<ContinueStmt>(S))4653 return RewriteContinueStmt(StmtContinueStmt);4654 4655 // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls4656 // and cast exprs.4657 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {4658 // FIXME: What we're doing here is modifying the type-specifier that4659 // precedes the first Decl. In the future the DeclGroup should have4660 // a separate type-specifier that we can rewrite.4661 // NOTE: We need to avoid rewriting the DeclStmt if it is within4662 // the context of an ObjCForCollectionStmt. For example:4663 // NSArray *someArray;4664 // for (id <FooProtocol> index in someArray) ;4665 // This is because RewriteObjCForCollectionStmt() does textual rewriting4666 // and it depends on the original text locations/positions.4667 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))4668 RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());4669 4670 // Blocks rewrite rules.4671 for (auto *SD : DS->decls()) {4672 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {4673 if (isTopLevelBlockPointerType(ND->getType()))4674 RewriteBlockPointerDecl(ND);4675 else if (ND->getType()->isFunctionPointerType())4676 CheckFunctionPointerDecl(ND->getType(), ND);4677 if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {4678 if (VD->hasAttr<BlocksAttr>()) {4679 static unsigned uniqueByrefDeclCount = 0;4680 assert(!BlockByRefDeclNo.count(ND) &&4681 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");4682 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;4683 RewriteByRefVar(VD);4684 }4685 else4686 RewriteTypeOfDecl(VD);4687 }4688 }4689 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {4690 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))4691 RewriteBlockPointerDecl(TD);4692 else if (TD->getUnderlyingType()->isFunctionPointerType())4693 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);4694 }4695 }4696 }4697 4698 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))4699 RewriteObjCQualifiedInterfaceTypes(CE);4700 4701 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||4702 isa<DoStmt>(S) || isa<ForStmt>(S)) {4703 assert(!Stmts.empty() && "Statement stack is empty");4704 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||4705 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))4706 && "Statement stack mismatch");4707 Stmts.pop_back();4708 }4709 // Handle blocks rewriting.4710 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {4711 ValueDecl *VD = DRE->getDecl();4712 if (VD->hasAttr<BlocksAttr>())4713 return RewriteBlockDeclRefExpr(DRE);4714 if (HasLocalVariableExternalStorage(VD))4715 return RewriteLocalVariableExternalStorage(DRE);4716 }4717 4718 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {4719 if (CE->getCallee()->getType()->isBlockPointerType()) {4720 Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());4721 ReplaceStmt(S, BlockCall);4722 return BlockCall;4723 }4724 }4725 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {4726 RewriteCastExpr(CE);4727 }4728#if 04729 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {4730 CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),4731 ICE->getSubExpr(),4732 SourceLocation());4733 // Get the new text.4734 std::string SStr;4735 llvm::raw_string_ostream Buf(SStr);4736 Replacement->printPretty(Buf);4737 const std::string &Str = Buf.str();4738 4739 printf("CAST = %s\n", &Str[0]);4740 InsertText(ICE->getSubExpr()->getBeginLoc(), Str);4741 delete S;4742 return Replacement;4743 }4744#endif4745 // Return this stmt unmodified.4746 return S;4747}4748 4749void RewriteObjC::RewriteRecordBody(RecordDecl *RD) {4750 for (auto *FD : RD->fields()) {4751 if (isTopLevelBlockPointerType(FD->getType()))4752 RewriteBlockPointerDecl(FD);4753 if (FD->getType()->isObjCQualifiedIdType() ||4754 FD->getType()->isObjCQualifiedInterfaceType())4755 RewriteObjCQualifiedInterfaceTypes(FD);4756 }4757}4758 4759/// HandleDeclInMainFile - This is called for each top-level decl defined in the4760/// main file of the input.4761void RewriteObjC::HandleDeclInMainFile(Decl *D) {4762 switch (D->getKind()) {4763 case Decl::Function: {4764 FunctionDecl *FD = cast<FunctionDecl>(D);4765 if (FD->isOverloadedOperator())4766 return;4767 4768 // Since function prototypes don't have ParmDecl's, we check the function4769 // prototype. This enables us to rewrite function declarations and4770 // definitions using the same code.4771 RewriteBlocksInFunctionProtoType(FD->getType(), FD);4772 4773 if (!FD->isThisDeclarationADefinition())4774 break;4775 4776 // FIXME: If this should support Obj-C++, support CXXTryStmt4777 if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {4778 CurFunctionDef = FD;4779 CurFunctionDeclToDeclareForBlock = FD;4780 CurrentBody = Body;4781 Body =4782 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));4783 FD->setBody(Body);4784 CurrentBody = nullptr;4785 if (PropParentMap) {4786 delete PropParentMap;4787 PropParentMap = nullptr;4788 }4789 // This synthesizes and inserts the block "impl" struct, invoke function,4790 // and any copy/dispose helper functions.4791 InsertBlockLiteralsWithinFunction(FD);4792 CurFunctionDef = nullptr;4793 CurFunctionDeclToDeclareForBlock = nullptr;4794 }4795 break;4796 }4797 case Decl::ObjCMethod: {4798 ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);4799 if (CompoundStmt *Body = MD->getCompoundBody()) {4800 CurMethodDef = MD;4801 CurrentBody = Body;4802 Body =4803 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));4804 MD->setBody(Body);4805 CurrentBody = nullptr;4806 if (PropParentMap) {4807 delete PropParentMap;4808 PropParentMap = nullptr;4809 }4810 InsertBlockLiteralsWithinMethod(MD);4811 CurMethodDef = nullptr;4812 }4813 break;4814 }4815 case Decl::ObjCImplementation: {4816 ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);4817 ClassImplementation.push_back(CI);4818 break;4819 }4820 case Decl::ObjCCategoryImpl: {4821 ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);4822 CategoryImplementation.push_back(CI);4823 break;4824 }4825 case Decl::Var: {4826 VarDecl *VD = cast<VarDecl>(D);4827 RewriteObjCQualifiedInterfaceTypes(VD);4828 if (isTopLevelBlockPointerType(VD->getType()))4829 RewriteBlockPointerDecl(VD);4830 else if (VD->getType()->isFunctionPointerType()) {4831 CheckFunctionPointerDecl(VD->getType(), VD);4832 if (VD->getInit()) {4833 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {4834 RewriteCastExpr(CE);4835 }4836 }4837 } else if (VD->getType()->isRecordType()) {4838 auto *RD = VD->getType()->castAsRecordDecl();4839 if (RD->isCompleteDefinition())4840 RewriteRecordBody(RD);4841 }4842 if (VD->getInit()) {4843 GlobalVarDecl = VD;4844 CurrentBody = VD->getInit();4845 RewriteFunctionBodyOrGlobalInitializer(VD->getInit());4846 CurrentBody = nullptr;4847 if (PropParentMap) {4848 delete PropParentMap;4849 PropParentMap = nullptr;4850 }4851 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());4852 GlobalVarDecl = nullptr;4853 4854 // This is needed for blocks.4855 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {4856 RewriteCastExpr(CE);4857 }4858 }4859 break;4860 }4861 case Decl::TypeAlias:4862 case Decl::Typedef: {4863 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {4864 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))4865 RewriteBlockPointerDecl(TD);4866 else if (TD->getUnderlyingType()->isFunctionPointerType())4867 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);4868 }4869 break;4870 }4871 case Decl::CXXRecord:4872 case Decl::Record: {4873 RecordDecl *RD = cast<RecordDecl>(D);4874 if (RD->isCompleteDefinition())4875 RewriteRecordBody(RD);4876 break;4877 }4878 default:4879 break;4880 }4881 // Nothing yet.4882}4883 4884void RewriteObjC::HandleTranslationUnit(ASTContext &C) {4885 if (Diags.hasErrorOccurred())4886 return;4887 4888 RewriteInclude();4889 4890 // Here's a great place to add any extra declarations that may be needed.4891 // Write out meta data for each @protocol(<expr>).4892 for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls)4893 RewriteObjCProtocolMetaData(ProtDecl, "", "", Preamble);4894 4895 InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);4896 if (ClassImplementation.size() || CategoryImplementation.size())4897 RewriteImplementations();4898 4899 // Get the buffer corresponding to MainFileID. If we haven't changed it, then4900 // we are done.4901 if (const RewriteBuffer *RewriteBuf =4902 Rewrite.getRewriteBufferFor(MainFileID)) {4903 //printf("Changed:\n");4904 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());4905 } else {4906 llvm::errs() << "No changes\n";4907 }4908 4909 if (ClassImplementation.size() || CategoryImplementation.size() ||4910 ProtocolExprDecls.size()) {4911 // Rewrite Objective-c meta data*4912 std::string ResultStr;4913 RewriteMetaDataIntoBuffer(ResultStr);4914 // Emit metadata.4915 *OutFile << ResultStr;4916 }4917 OutFile->flush();4918}4919 4920void RewriteObjCFragileABI::Initialize(ASTContext &context) {4921 InitializeCommon(context);4922 4923 // declaring objc_selector outside the parameter list removes a silly4924 // scope related warning...4925 if (IsHeader)4926 Preamble = "#pragma once\n";4927 Preamble += "struct objc_selector; struct objc_class;\n";4928 Preamble += "struct __rw_objc_super { struct objc_object *object; ";4929 Preamble += "struct objc_object *superClass; ";4930 if (LangOpts.MicrosoftExt) {4931 // Add a constructor for creating temporary objects.4932 Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "4933 ": ";4934 Preamble += "object(o), superClass(s) {} ";4935 }4936 Preamble += "};\n";4937 Preamble += "#ifndef _REWRITER_typedef_Protocol\n";4938 Preamble += "typedef struct objc_object Protocol;\n";4939 Preamble += "#define _REWRITER_typedef_Protocol\n";4940 Preamble += "#endif\n";4941 if (LangOpts.MicrosoftExt) {4942 Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";4943 Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";4944 } else4945 Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";4946 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";4947 Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";4948 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";4949 Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";4950 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret";4951 Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";4952 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret";4953 Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";4954 Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";4955 Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";4956 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";4957 Preamble += "(const char *);\n";4958 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";4959 Preamble += "(struct objc_class *);\n";4960 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";4961 Preamble += "(const char *);\n";4962 Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";4963 Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";4964 Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";4965 Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";4966 Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";4967 Preamble += "(struct objc_class *, struct objc_object *);\n";4968 // @synchronized hooks.4969 Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n";4970 Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n";4971 Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";4972 Preamble += "#ifndef __FASTENUMERATIONSTATE\n";4973 Preamble += "struct __objcFastEnumerationState {\n\t";4974 Preamble += "unsigned long state;\n\t";4975 Preamble += "void **itemsPtr;\n\t";4976 Preamble += "unsigned long *mutationsPtr;\n\t";4977 Preamble += "unsigned long extra[5];\n};\n";4978 Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";4979 Preamble += "#define __FASTENUMERATIONSTATE\n";4980 Preamble += "#endif\n";4981 Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";4982 Preamble += "struct __NSConstantStringImpl {\n";4983 Preamble += " int *isa;\n";4984 Preamble += " int flags;\n";4985 Preamble += " char *str;\n";4986 Preamble += " long length;\n";4987 Preamble += "};\n";4988 Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";4989 Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";4990 Preamble += "#else\n";4991 Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";4992 Preamble += "#endif\n";4993 Preamble += "#define __NSCONSTANTSTRINGIMPL\n";4994 Preamble += "#endif\n";4995 // Blocks preamble.4996 Preamble += "#ifndef BLOCK_IMPL\n";4997 Preamble += "#define BLOCK_IMPL\n";4998 Preamble += "struct __block_impl {\n";4999 Preamble += " void *isa;\n";5000 Preamble += " int Flags;\n";5001 Preamble += " int Reserved;\n";5002 Preamble += " void *FuncPtr;\n";5003 Preamble += "};\n";5004 Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";5005 Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";5006 Preamble += "extern \"C\" __declspec(dllexport) "5007 "void _Block_object_assign(void *, const void *, const int);\n";5008 Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";5009 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";5010 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";5011 Preamble += "#else\n";5012 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";5013 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";5014 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";5015 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";5016 Preamble += "#endif\n";5017 Preamble += "#endif\n";5018 if (LangOpts.MicrosoftExt) {5019 Preamble += "#undef __OBJC_RW_DLLIMPORT\n";5020 Preamble += "#undef __OBJC_RW_STATICIMPORT\n";5021 Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.5022 Preamble += "#define __attribute__(X)\n";5023 Preamble += "#endif\n";5024 Preamble += "#define __weak\n";5025 }5026 else {5027 Preamble += "#define __block\n";5028 Preamble += "#define __weak\n";5029 }5030 // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long5031 // as this avoids warning in any 64bit/32bit compilation model.5032 Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";5033}5034 5035/// RewriteIvarOffsetComputation - This routine synthesizes computation of5036/// ivar offset.5037void RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,5038 std::string &Result) {5039 if (ivar->isBitField()) {5040 // FIXME: The hack below doesn't work for bitfields. For now, we simply5041 // place all bitfields at offset 0.5042 Result += "0";5043 } else {5044 Result += "__OFFSETOFIVAR__(struct ";5045 Result += ivar->getContainingInterface()->getNameAsString();5046 if (LangOpts.MicrosoftExt)5047 Result += "_IMPL";5048 Result += ", ";5049 Result += ivar->getNameAsString();5050 Result += ")";5051 }5052}5053 5054/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.5055void RewriteObjCFragileABI::RewriteObjCProtocolMetaData(5056 ObjCProtocolDecl *PDecl, StringRef prefix,5057 StringRef ClassName, std::string &Result) {5058 static bool objc_protocol_methods = false;5059 5060 // Output struct protocol_methods holder of method selector and type.5061 if (!objc_protocol_methods && PDecl->hasDefinition()) {5062 /* struct protocol_methods {5063 SEL _cmd;5064 char *method_types;5065 }5066 */5067 Result += "\nstruct _protocol_methods {\n";5068 Result += "\tstruct objc_selector *_cmd;\n";5069 Result += "\tchar *method_types;\n";5070 Result += "};\n";5071 5072 objc_protocol_methods = true;5073 }5074 // Do not synthesize the protocol more than once.5075 if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))5076 return;5077 5078 if (ObjCProtocolDecl *Def = PDecl->getDefinition())5079 PDecl = Def;5080 5081 if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {5082 unsigned NumMethods = std::distance(PDecl->instmeth_begin(),5083 PDecl->instmeth_end());5084 /* struct _objc_protocol_method_list {5085 int protocol_method_count;5086 struct protocol_methods protocols[];5087 }5088 */5089 Result += "\nstatic struct {\n";5090 Result += "\tint protocol_method_count;\n";5091 Result += "\tstruct _protocol_methods protocol_methods[";5092 Result += utostr(NumMethods);5093 Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_";5094 Result += PDecl->getNameAsString();5095 Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= "5096 "{\n\t" + utostr(NumMethods) + "\n";5097 5098 // Output instance methods declared in this protocol.5099 for (ObjCProtocolDecl::instmeth_iterator5100 I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();5101 I != E; ++I) {5102 if (I == PDecl->instmeth_begin())5103 Result += "\t ,{{(struct objc_selector *)\"";5104 else5105 Result += "\t ,{(struct objc_selector *)\"";5106 Result += (*I)->getSelector().getAsString();5107 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);5108 Result += "\", \"";5109 Result += MethodTypeString;5110 Result += "\"}\n";5111 }5112 Result += "\t }\n};\n";5113 }5114 5115 // Output class methods declared in this protocol.5116 unsigned NumMethods = std::distance(PDecl->classmeth_begin(),5117 PDecl->classmeth_end());5118 if (NumMethods > 0) {5119 /* struct _objc_protocol_method_list {5120 int protocol_method_count;5121 struct protocol_methods protocols[];5122 }5123 */5124 Result += "\nstatic struct {\n";5125 Result += "\tint protocol_method_count;\n";5126 Result += "\tstruct _protocol_methods protocol_methods[";5127 Result += utostr(NumMethods);5128 Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_";5129 Result += PDecl->getNameAsString();5130 Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "5131 "{\n\t";5132 Result += utostr(NumMethods);5133 Result += "\n";5134 5135 // Output instance methods declared in this protocol.5136 for (ObjCProtocolDecl::classmeth_iterator5137 I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();5138 I != E; ++I) {5139 if (I == PDecl->classmeth_begin())5140 Result += "\t ,{{(struct objc_selector *)\"";5141 else5142 Result += "\t ,{(struct objc_selector *)\"";5143 Result += (*I)->getSelector().getAsString();5144 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(*I);5145 Result += "\", \"";5146 Result += MethodTypeString;5147 Result += "\"}\n";5148 }5149 Result += "\t }\n};\n";5150 }5151 5152 // Output:5153 /* struct _objc_protocol {5154 // Objective-C 1.0 extensions5155 struct _objc_protocol_extension *isa;5156 char *protocol_name;5157 struct _objc_protocol **protocol_list;5158 struct _objc_protocol_method_list *instance_methods;5159 struct _objc_protocol_method_list *class_methods;5160 };5161 */5162 static bool objc_protocol = false;5163 if (!objc_protocol) {5164 Result += "\nstruct _objc_protocol {\n";5165 Result += "\tstruct _objc_protocol_extension *isa;\n";5166 Result += "\tchar *protocol_name;\n";5167 Result += "\tstruct _objc_protocol **protocol_list;\n";5168 Result += "\tstruct _objc_protocol_method_list *instance_methods;\n";5169 Result += "\tstruct _objc_protocol_method_list *class_methods;\n";5170 Result += "};\n";5171 5172 objc_protocol = true;5173 }5174 5175 Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_";5176 Result += PDecl->getNameAsString();5177 Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= "5178 "{\n\t0, \"";5179 Result += PDecl->getNameAsString();5180 Result += "\", 0, ";5181 if (PDecl->instmeth_begin() != PDecl->instmeth_end()) {5182 Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";5183 Result += PDecl->getNameAsString();5184 Result += ", ";5185 }5186 else5187 Result += "0, ";5188 if (PDecl->classmeth_begin() != PDecl->classmeth_end()) {5189 Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_";5190 Result += PDecl->getNameAsString();5191 Result += "\n";5192 }5193 else5194 Result += "0\n";5195 Result += "};\n";5196 5197 // Mark this protocol as having been generated.5198 if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)5199 llvm_unreachable("protocol already synthesized");5200}5201 5202void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData(5203 const ObjCList<ObjCProtocolDecl> &Protocols,5204 StringRef prefix, StringRef ClassName,5205 std::string &Result) {5206 if (Protocols.empty()) return;5207 5208 for (unsigned i = 0; i != Protocols.size(); i++)5209 RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result);5210 5211 // Output the top lovel protocol meta-data for the class.5212 /* struct _objc_protocol_list {5213 struct _objc_protocol_list *next;5214 int protocol_count;5215 struct _objc_protocol *class_protocols[];5216 }5217 */5218 Result += "\nstatic struct {\n";5219 Result += "\tstruct _objc_protocol_list *next;\n";5220 Result += "\tint protocol_count;\n";5221 Result += "\tstruct _objc_protocol *class_protocols[";5222 Result += utostr(Protocols.size());5223 Result += "];\n} _OBJC_";5224 Result += prefix;5225 Result += "_PROTOCOLS_";5226 Result += ClassName;5227 Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= "5228 "{\n\t0, ";5229 Result += utostr(Protocols.size());5230 Result += "\n";5231 5232 Result += "\t,{&_OBJC_PROTOCOL_";5233 Result += Protocols[0]->getNameAsString();5234 Result += " \n";5235 5236 for (unsigned i = 1; i != Protocols.size(); i++) {5237 Result += "\t ,&_OBJC_PROTOCOL_";5238 Result += Protocols[i]->getNameAsString();5239 Result += "\n";5240 }5241 Result += "\t }\n};\n";5242}5243 5244void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,5245 std::string &Result) {5246 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();5247 5248 // Explicitly declared @interface's are already synthesized.5249 if (CDecl->isImplicitInterfaceDecl()) {5250 // FIXME: Implementation of a class with no @interface (legacy) does not5251 // produce correct synthesis as yet.5252 RewriteObjCInternalStruct(CDecl, Result);5253 }5254 5255 // Build _objc_ivar_list metadata for classes ivars if needed5256 unsigned NumIvars =5257 !IDecl->ivar_empty() ? IDecl->ivar_size() : CDecl->ivar_size();5258 if (NumIvars > 0) {5259 static bool objc_ivar = false;5260 if (!objc_ivar) {5261 /* struct _objc_ivar {5262 char *ivar_name;5263 char *ivar_type;5264 int ivar_offset;5265 };5266 */5267 Result += "\nstruct _objc_ivar {\n";5268 Result += "\tchar *ivar_name;\n";5269 Result += "\tchar *ivar_type;\n";5270 Result += "\tint ivar_offset;\n";5271 Result += "};\n";5272 5273 objc_ivar = true;5274 }5275 5276 /* struct {5277 int ivar_count;5278 struct _objc_ivar ivar_list[nIvars];5279 };5280 */5281 Result += "\nstatic struct {\n";5282 Result += "\tint ivar_count;\n";5283 Result += "\tstruct _objc_ivar ivar_list[";5284 Result += utostr(NumIvars);5285 Result += "];\n} _OBJC_INSTANCE_VARIABLES_";5286 Result += IDecl->getNameAsString();5287 Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= "5288 "{\n\t";5289 Result += utostr(NumIvars);5290 Result += "\n";5291 5292 ObjCInterfaceDecl::ivar_iterator IVI, IVE;5293 SmallVector<ObjCIvarDecl *, 8> IVars;5294 if (!IDecl->ivar_empty()) {5295 for (auto *IV : IDecl->ivars())5296 IVars.push_back(IV);5297 IVI = IDecl->ivar_begin();5298 IVE = IDecl->ivar_end();5299 } else {5300 IVI = CDecl->ivar_begin();5301 IVE = CDecl->ivar_end();5302 }5303 Result += "\t,{{\"";5304 Result += IVI->getNameAsString();5305 Result += "\", \"";5306 std::string TmpString, StrEncoding;5307 Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);5308 QuoteDoublequotes(TmpString, StrEncoding);5309 Result += StrEncoding;5310 Result += "\", ";5311 RewriteIvarOffsetComputation(*IVI, Result);5312 Result += "}\n";5313 for (++IVI; IVI != IVE; ++IVI) {5314 Result += "\t ,{\"";5315 Result += IVI->getNameAsString();5316 Result += "\", \"";5317 std::string TmpString, StrEncoding;5318 Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI);5319 QuoteDoublequotes(TmpString, StrEncoding);5320 Result += StrEncoding;5321 Result += "\", ";5322 RewriteIvarOffsetComputation(*IVI, Result);5323 Result += "}\n";5324 }5325 5326 Result += "\t }\n};\n";5327 }5328 5329 // Build _objc_method_list for class's instance methods if needed5330 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());5331 5332 // If any of our property implementations have associated getters or5333 // setters, produce metadata for them as well.5334 for (const auto *Prop : IDecl->property_impls()) {5335 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)5336 continue;5337 if (!Prop->getPropertyIvarDecl())5338 continue;5339 ObjCPropertyDecl *PD = Prop->getPropertyDecl();5340 if (!PD)5341 continue;5342 if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())5343 if (!Getter->isDefined())5344 InstanceMethods.push_back(Getter);5345 if (PD->isReadOnly())5346 continue;5347 if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())5348 if (!Setter->isDefined())5349 InstanceMethods.push_back(Setter);5350 }5351 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),5352 true, "", IDecl->getName(), Result);5353 5354 // Build _objc_method_list for class's class methods if needed5355 RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),5356 false, "", IDecl->getName(), Result);5357 5358 // Protocols referenced in class declaration?5359 RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(),5360 "CLASS", CDecl->getName(), Result);5361 5362 // Declaration of class/meta-class metadata5363 /* struct _objc_class {5364 struct _objc_class *isa; // or const char *root_class_name when metadata5365 const char *super_class_name;5366 char *name;5367 long version;5368 long info;5369 long instance_size;5370 struct _objc_ivar_list *ivars;5371 struct _objc_method_list *methods;5372 struct objc_cache *cache;5373 struct objc_protocol_list *protocols;5374 const char *ivar_layout;5375 struct _objc_class_ext *ext;5376 };5377 */5378 static bool objc_class = false;5379 if (!objc_class) {5380 Result += "\nstruct _objc_class {\n";5381 Result += "\tstruct _objc_class *isa;\n";5382 Result += "\tconst char *super_class_name;\n";5383 Result += "\tchar *name;\n";5384 Result += "\tlong version;\n";5385 Result += "\tlong info;\n";5386 Result += "\tlong instance_size;\n";5387 Result += "\tstruct _objc_ivar_list *ivars;\n";5388 Result += "\tstruct _objc_method_list *methods;\n";5389 Result += "\tstruct objc_cache *cache;\n";5390 Result += "\tstruct _objc_protocol_list *protocols;\n";5391 Result += "\tconst char *ivar_layout;\n";5392 Result += "\tstruct _objc_class_ext *ext;\n";5393 Result += "};\n";5394 objc_class = true;5395 }5396 5397 // Meta-class metadata generation.5398 ObjCInterfaceDecl *RootClass = nullptr;5399 ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();5400 while (SuperClass) {5401 RootClass = SuperClass;5402 SuperClass = SuperClass->getSuperClass();5403 }5404 SuperClass = CDecl->getSuperClass();5405 5406 Result += "\nstatic struct _objc_class _OBJC_METACLASS_";5407 Result += CDecl->getNameAsString();5408 Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= "5409 "{\n\t(struct _objc_class *)\"";5410 Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString());5411 Result += "\"";5412 5413 if (SuperClass) {5414 Result += ", \"";5415 Result += SuperClass->getNameAsString();5416 Result += "\", \"";5417 Result += CDecl->getNameAsString();5418 Result += "\"";5419 }5420 else {5421 Result += ", 0, \"";5422 Result += CDecl->getNameAsString();5423 Result += "\"";5424 }5425 // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it.5426 // 'info' field is initialized to CLS_META(2) for metaclass5427 Result += ", 0,2, sizeof(struct _objc_class), 0";5428 if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {5429 Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_";5430 Result += IDecl->getNameAsString();5431 Result += "\n";5432 }5433 else5434 Result += ", 0\n";5435 if (CDecl->protocol_begin() != CDecl->protocol_end()) {5436 Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_";5437 Result += CDecl->getNameAsString();5438 Result += ",0,0\n";5439 }5440 else5441 Result += "\t,0,0,0,0\n";5442 Result += "};\n";5443 5444 // class metadata generation.5445 Result += "\nstatic struct _objc_class _OBJC_CLASS_";5446 Result += CDecl->getNameAsString();5447 Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= "5448 "{\n\t&_OBJC_METACLASS_";5449 Result += CDecl->getNameAsString();5450 if (SuperClass) {5451 Result += ", \"";5452 Result += SuperClass->getNameAsString();5453 Result += "\", \"";5454 Result += CDecl->getNameAsString();5455 Result += "\"";5456 }5457 else {5458 Result += ", 0, \"";5459 Result += CDecl->getNameAsString();5460 Result += "\"";5461 }5462 // 'info' field is initialized to CLS_CLASS(1) for class5463 Result += ", 0,1";5464 if (!ObjCSynthesizedStructs.count(CDecl))5465 Result += ",0";5466 else {5467 // class has size. Must synthesize its size.5468 Result += ",sizeof(struct ";5469 Result += CDecl->getNameAsString();5470 if (LangOpts.MicrosoftExt)5471 Result += "_IMPL";5472 Result += ")";5473 }5474 if (NumIvars > 0) {5475 Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_";5476 Result += CDecl->getNameAsString();5477 Result += "\n\t";5478 }5479 else5480 Result += ",0";5481 if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {5482 Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_";5483 Result += CDecl->getNameAsString();5484 Result += ", 0\n\t";5485 }5486 else5487 Result += ",0,0";5488 if (CDecl->protocol_begin() != CDecl->protocol_end()) {5489 Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_";5490 Result += CDecl->getNameAsString();5491 Result += ", 0,0\n";5492 }5493 else5494 Result += ",0,0,0\n";5495 Result += "};\n";5496}5497 5498void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) {5499 int ClsDefCount = ClassImplementation.size();5500 int CatDefCount = CategoryImplementation.size();5501 5502 // For each implemented class, write out all its meta data.5503 for (int i = 0; i < ClsDefCount; i++)5504 RewriteObjCClassMetaData(ClassImplementation[i], Result);5505 5506 // For each implemented category, write out all its meta data.5507 for (int i = 0; i < CatDefCount; i++)5508 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);5509 5510 // Write objc_symtab metadata5511 /*5512 struct _objc_symtab5513 {5514 long sel_ref_cnt;5515 SEL *refs;5516 short cls_def_cnt;5517 short cat_def_cnt;5518 void *defs[cls_def_cnt + cat_def_cnt];5519 };5520 */5521 5522 Result += "\nstruct _objc_symtab {\n";5523 Result += "\tlong sel_ref_cnt;\n";5524 Result += "\tSEL *refs;\n";5525 Result += "\tshort cls_def_cnt;\n";5526 Result += "\tshort cat_def_cnt;\n";5527 Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n";5528 Result += "};\n\n";5529 5530 Result += "static struct _objc_symtab "5531 "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n";5532 Result += "\t0, 0, " + utostr(ClsDefCount)5533 + ", " + utostr(CatDefCount) + "\n";5534 for (int i = 0; i < ClsDefCount; i++) {5535 Result += "\t,&_OBJC_CLASS_";5536 Result += ClassImplementation[i]->getNameAsString();5537 Result += "\n";5538 }5539 5540 for (int i = 0; i < CatDefCount; i++) {5541 Result += "\t,&_OBJC_CATEGORY_";5542 Result += CategoryImplementation[i]->getClassInterface()->getNameAsString();5543 Result += "_";5544 Result += CategoryImplementation[i]->getNameAsString();5545 Result += "\n";5546 }5547 5548 Result += "};\n\n";5549 5550 // Write objc_module metadata5551 5552 /*5553 struct _objc_module {5554 long version;5555 long size;5556 const char *name;5557 struct _objc_symtab *symtab;5558 }5559 */5560 5561 Result += "\nstruct _objc_module {\n";5562 Result += "\tlong version;\n";5563 Result += "\tlong size;\n";5564 Result += "\tconst char *name;\n";5565 Result += "\tstruct _objc_symtab *symtab;\n";5566 Result += "};\n\n";5567 Result += "static struct _objc_module "5568 "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n";5569 Result += "\t" + utostr(OBJC_ABI_VERSION) +5570 ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n";5571 Result += "};\n\n";5572 5573 if (LangOpts.MicrosoftExt) {5574 if (ProtocolExprDecls.size()) {5575 Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n";5576 Result += "#pragma data_seg(push, \".objc_protocol$B\")\n";5577 for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {5578 Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_";5579 Result += ProtDecl->getNameAsString();5580 Result += " = &_OBJC_PROTOCOL_";5581 Result += ProtDecl->getNameAsString();5582 Result += ";\n";5583 }5584 Result += "#pragma data_seg(pop)\n\n";5585 }5586 Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n";5587 Result += "#pragma data_seg(push, \".objc_module_info$B\")\n";5588 Result += "static struct _objc_module *_POINTER_OBJC_MODULES = ";5589 Result += "&_OBJC_MODULES;\n";5590 Result += "#pragma data_seg(pop)\n\n";5591 }5592}5593 5594/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category5595/// implementation.5596void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,5597 std::string &Result) {5598 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();5599 // Find category declaration for this implementation.5600 ObjCCategoryDecl *CDecl5601 = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());5602 5603 std::string FullCategoryName = ClassDecl->getNameAsString();5604 FullCategoryName += '_';5605 FullCategoryName += IDecl->getNameAsString();5606 5607 // Build _objc_method_list for class's instance methods if needed5608 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());5609 5610 // If any of our property implementations have associated getters or5611 // setters, produce metadata for them as well.5612 for (const auto *Prop : IDecl->property_impls()) {5613 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)5614 continue;5615 if (!Prop->getPropertyIvarDecl())5616 continue;5617 ObjCPropertyDecl *PD = Prop->getPropertyDecl();5618 if (!PD)5619 continue;5620 if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())5621 InstanceMethods.push_back(Getter);5622 if (PD->isReadOnly())5623 continue;5624 if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())5625 InstanceMethods.push_back(Setter);5626 }5627 RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(),5628 true, "CATEGORY_", FullCategoryName, Result);5629 5630 // Build _objc_method_list for class's class methods if needed5631 RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(),5632 false, "CATEGORY_", FullCategoryName, Result);5633 5634 // Protocols referenced in class declaration?5635 // Null CDecl is case of a category implementation with no category interface5636 if (CDecl)5637 RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY",5638 FullCategoryName, Result);5639 /* struct _objc_category {5640 char *category_name;5641 char *class_name;5642 struct _objc_method_list *instance_methods;5643 struct _objc_method_list *class_methods;5644 struct _objc_protocol_list *protocols;5645 // Objective-C 1.0 extensions5646 uint32_t size; // sizeof (struct _objc_category)5647 struct _objc_property_list *instance_properties; // category's own5648 // @property decl.5649 };5650 */5651 5652 static bool objc_category = false;5653 if (!objc_category) {5654 Result += "\nstruct _objc_category {\n";5655 Result += "\tchar *category_name;\n";5656 Result += "\tchar *class_name;\n";5657 Result += "\tstruct _objc_method_list *instance_methods;\n";5658 Result += "\tstruct _objc_method_list *class_methods;\n";5659 Result += "\tstruct _objc_protocol_list *protocols;\n";5660 Result += "\tunsigned int size;\n";5661 Result += "\tstruct _objc_property_list *instance_properties;\n";5662 Result += "};\n";5663 objc_category = true;5664 }5665 Result += "\nstatic struct _objc_category _OBJC_CATEGORY_";5666 Result += FullCategoryName;5667 Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\"";5668 Result += IDecl->getNameAsString();5669 Result += "\"\n\t, \"";5670 Result += ClassDecl->getNameAsString();5671 Result += "\"\n";5672 5673 if (IDecl->instmeth_begin() != IDecl->instmeth_end()) {5674 Result += "\t, (struct _objc_method_list *)"5675 "&_OBJC_CATEGORY_INSTANCE_METHODS_";5676 Result += FullCategoryName;5677 Result += "\n";5678 }5679 else5680 Result += "\t, 0\n";5681 if (IDecl->classmeth_begin() != IDecl->classmeth_end()) {5682 Result += "\t, (struct _objc_method_list *)"5683 "&_OBJC_CATEGORY_CLASS_METHODS_";5684 Result += FullCategoryName;5685 Result += "\n";5686 }5687 else5688 Result += "\t, 0\n";5689 5690 if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) {5691 Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_";5692 Result += FullCategoryName;5693 Result += "\n";5694 }5695 else5696 Result += "\t, 0\n";5697 Result += "\t, sizeof(struct _objc_category), 0\n};\n";5698}5699 5700// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or5701/// class methods.5702template<typename MethodIterator>5703void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,5704 MethodIterator MethodEnd,5705 bool IsInstanceMethod,5706 StringRef prefix,5707 StringRef ClassName,5708 std::string &Result) {5709 if (MethodBegin == MethodEnd) return;5710 5711 if (!objc_impl_method) {5712 /* struct _objc_method {5713 SEL _cmd;5714 char *method_types;5715 void *_imp;5716 }5717 */5718 Result += "\nstruct _objc_method {\n";5719 Result += "\tSEL _cmd;\n";5720 Result += "\tchar *method_types;\n";5721 Result += "\tvoid *_imp;\n";5722 Result += "};\n";5723 5724 objc_impl_method = true;5725 }5726 5727 // Build _objc_method_list for class's methods if needed5728 5729 /* struct {5730 struct _objc_method_list *next_method;5731 int method_count;5732 struct _objc_method method_list[];5733 }5734 */5735 unsigned NumMethods = std::distance(MethodBegin, MethodEnd);5736 Result += "\nstatic struct {\n";5737 Result += "\tstruct _objc_method_list *next_method;\n";5738 Result += "\tint method_count;\n";5739 Result += "\tstruct _objc_method method_list[";5740 Result += utostr(NumMethods);5741 Result += "];\n} _OBJC_";5742 Result += prefix;5743 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";5744 Result += "_METHODS_";5745 Result += ClassName;5746 Result += " __attribute__ ((used, section (\"__OBJC, __";5747 Result += IsInstanceMethod ? "inst" : "cls";5748 Result += "_meth\")))= ";5749 Result += "{\n\t0, " + utostr(NumMethods) + "\n";5750 5751 Result += "\t,{{(SEL)\"";5752 Result += (*MethodBegin)->getSelector().getAsString();5753 std::string MethodTypeString =5754 Context->getObjCEncodingForMethodDecl(*MethodBegin);5755 Result += "\", \"";5756 Result += MethodTypeString;5757 Result += "\", (void *)";5758 Result += MethodInternalNames[*MethodBegin];5759 Result += "}\n";5760 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {5761 Result += "\t ,{(SEL)\"";5762 Result += (*MethodBegin)->getSelector().getAsString();5763 std::string MethodTypeString =5764 Context->getObjCEncodingForMethodDecl(*MethodBegin);5765 Result += "\", \"";5766 Result += MethodTypeString;5767 Result += "\", (void *)";5768 Result += MethodInternalNames[*MethodBegin];5769 Result += "}\n";5770 }5771 Result += "\t }\n};\n";5772}5773 5774Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {5775 SourceRange OldRange = IV->getSourceRange();5776 Expr *BaseExpr = IV->getBase();5777 5778 // Rewrite the base, but without actually doing replaces.5779 {5780 DisableReplaceStmtScope S(*this);5781 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));5782 IV->setBase(BaseExpr);5783 }5784 5785 ObjCIvarDecl *D = IV->getDecl();5786 5787 Expr *Replacement = IV;5788 if (CurMethodDef) {5789 if (BaseExpr->getType()->isObjCObjectPointerType()) {5790 const ObjCInterfaceType *iFaceDecl =5791 dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());5792 assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");5793 // lookup which class implements the instance variable.5794 ObjCInterfaceDecl *clsDeclared = nullptr;5795 iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),5796 clsDeclared);5797 assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");5798 5799 // Synthesize an explicit cast to gain access to the ivar.5800 std::string RecName =5801 std::string(clsDeclared->getIdentifier()->getName());5802 RecName += "_IMPL";5803 IdentifierInfo *II = &Context->Idents.get(RecName);5804 RecordDecl *RD =5805 RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,5806 SourceLocation(), SourceLocation(), II);5807 assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");5808 QualType castT =5809 Context->getPointerType(Context->getCanonicalTagType(RD));5810 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,5811 CK_BitCast,5812 IV->getBase());5813 // Don't forget the parens to enforce the proper binding.5814 ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(),5815 OldRange.getEnd(),5816 castExpr);5817 if (IV->isFreeIvar() &&5818 declaresSameEntity(CurMethodDef->getClassInterface(),5819 iFaceDecl->getDecl())) {5820 MemberExpr *ME = MemberExpr::CreateImplicit(5821 *Context, PE, true, D, D->getType(), VK_LValue, OK_Ordinary);5822 Replacement = ME;5823 } else {5824 IV->setBase(PE);5825 }5826 }5827 } else { // we are outside a method.5828 assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");5829 5830 // Explicit ivar refs need to have a cast inserted.5831 // FIXME: consider sharing some of this code with the code above.5832 if (BaseExpr->getType()->isObjCObjectPointerType()) {5833 const ObjCInterfaceType *iFaceDecl =5834 dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());5835 // lookup which class implements the instance variable.5836 ObjCInterfaceDecl *clsDeclared = nullptr;5837 iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),5838 clsDeclared);5839 assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");5840 5841 // Synthesize an explicit cast to gain access to the ivar.5842 std::string RecName =5843 std::string(clsDeclared->getIdentifier()->getName());5844 RecName += "_IMPL";5845 IdentifierInfo *II = &Context->Idents.get(RecName);5846 RecordDecl *RD =5847 RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,5848 SourceLocation(), SourceLocation(), II);5849 assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");5850 QualType castT =5851 Context->getPointerType(Context->getCanonicalTagType(RD));5852 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,5853 CK_BitCast,5854 IV->getBase());5855 // Don't forget the parens to enforce the proper binding.5856 ParenExpr *PE = new (Context) ParenExpr(5857 IV->getBase()->getBeginLoc(), IV->getBase()->getEndLoc(), castExpr);5858 // Cannot delete IV->getBase(), since PE points to it.5859 // Replace the old base with the cast. This is important when doing5860 // embedded rewrites. For example, [newInv->_container addObject:0].5861 IV->setBase(PE);5862 }5863 }5864 5865 ReplaceStmtWithRange(IV, Replacement, OldRange);5866 return Replacement;5867}5868 5869#endif // CLANG_ENABLE_OBJC_REWRITER5870