7527 lines · cpp
1//===-- RewriteModernObjC.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/AST/AST.h"14#include "clang/AST/ASTConsumer.h"15#include "clang/AST/Attr.h"16#include "clang/AST/ParentMap.h"17#include "clang/Basic/CharInfo.h"18#include "clang/Basic/Diagnostic.h"19#include "clang/Basic/IdentifierTable.h"20#include "clang/Basic/SourceManager.h"21#include "clang/Basic/TargetInfo.h"22#include "clang/Config/config.h"23#include "clang/Lex/Lexer.h"24#include "clang/Rewrite/Core/Rewriter.h"25#include "clang/Rewrite/Frontend/ASTConsumers.h"26#include "llvm/ADT/DenseSet.h"27#include "llvm/ADT/SetVector.h"28#include "llvm/ADT/SmallPtrSet.h"29#include "llvm/ADT/StringExtras.h"30#include "llvm/Support/MemoryBuffer.h"31#include "llvm/Support/raw_ostream.h"32#include <memory>33 34#if CLANG_ENABLE_OBJC_REWRITER35 36using namespace clang;37using llvm::RewriteBuffer;38using llvm::utostr;39 40namespace {41 class RewriteModernObjC : public ASTConsumer {42 protected:43 44 enum {45 BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),46 block, ... */47 BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */48 BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the49 __block variable */50 BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy51 helpers */52 BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose53 support routines */54 BLOCK_BYREF_CURRENT_MAX = 25655 };56 57 enum {58 BLOCK_NEEDS_FREE = (1 << 24),59 BLOCK_HAS_COPY_DISPOSE = (1 << 25),60 BLOCK_HAS_CXX_OBJ = (1 << 26),61 BLOCK_IS_GC = (1 << 27),62 BLOCK_IS_GLOBAL = (1 << 28),63 BLOCK_HAS_DESCRIPTOR = (1 << 29)64 };65 66 Rewriter Rewrite;67 DiagnosticsEngine &Diags;68 const LangOptions &LangOpts;69 ASTContext *Context;70 SourceManager *SM;71 TranslationUnitDecl *TUDecl;72 FileID MainFileID;73 const char *MainFileStart, *MainFileEnd;74 Stmt *CurrentBody;75 ParentMap *PropParentMap; // created lazily.76 std::string InFileName;77 std::unique_ptr<raw_ostream> OutFile;78 std::string Preamble;79 80 TypeDecl *ProtocolTypeDecl;81 VarDecl *GlobalVarDecl;82 Expr *GlobalConstructionExp;83 unsigned RewriteFailedDiag;84 unsigned GlobalBlockRewriteFailedDiag;85 // ObjC string constant support.86 unsigned NumObjCStringLiterals;87 VarDecl *ConstantStringClassReference;88 RecordDecl *NSStringRecord;89 90 // ObjC foreach break/continue generation support.91 int BcLabelCount;92 93 unsigned TryFinallyContainsReturnDiag;94 // Needed for super.95 ObjCMethodDecl *CurMethodDef;96 RecordDecl *SuperStructDecl;97 RecordDecl *ConstantStringDecl;98 99 FunctionDecl *MsgSendFunctionDecl;100 FunctionDecl *MsgSendSuperFunctionDecl;101 FunctionDecl *MsgSendStretFunctionDecl;102 FunctionDecl *MsgSendSuperStretFunctionDecl;103 FunctionDecl *MsgSendFpretFunctionDecl;104 FunctionDecl *GetClassFunctionDecl;105 FunctionDecl *GetMetaClassFunctionDecl;106 FunctionDecl *GetSuperClassFunctionDecl;107 FunctionDecl *SelGetUidFunctionDecl;108 FunctionDecl *CFStringFunctionDecl;109 FunctionDecl *SuperConstructorFunctionDecl;110 FunctionDecl *CurFunctionDef;111 112 /* Misc. containers needed for meta-data rewrite. */113 SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;114 SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;115 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;116 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;117 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces;118 llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags;119 SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen;120 /// DefinedNonLazyClasses - List of defined "non-lazy" classes.121 SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses;122 123 /// DefinedNonLazyCategories - List of defined "non-lazy" categories.124 SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories;125 126 SmallVector<Stmt *, 32> Stmts;127 SmallVector<int, 8> ObjCBcLabelNo;128 // Remember all the @protocol(<expr>) expressions.129 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;130 131 llvm::DenseSet<uint64_t> CopyDestroyCache;132 133 // Block expressions.134 SmallVector<BlockExpr *, 32> Blocks;135 SmallVector<int, 32> InnerDeclRefsCount;136 SmallVector<DeclRefExpr *, 32> InnerDeclRefs;137 138 SmallVector<DeclRefExpr *, 32> BlockDeclRefs;139 140 // Block related declarations.141 llvm::SmallSetVector<ValueDecl *, 8> BlockByCopyDecls;142 llvm::SmallSetVector<ValueDecl *, 8> BlockByRefDecls;143 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;144 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;145 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;146 147 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;148 llvm::DenseMap<ObjCInterfaceDecl *,149 llvm::SmallSetVector<ObjCIvarDecl *, 8> > ReferencedIvars;150 151 // ivar bitfield grouping containers152 llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups;153 llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber;154 // This container maps an <class, group number for ivar> tuple to the type155 // of the struct where the bitfield belongs.156 llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType;157 SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen;158 159 // This maps an original source AST to it's rewritten form. This allows160 // us to avoid rewriting the same node twice (which is very uncommon).161 // This is needed to support some of the exotic property rewriting.162 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;163 164 // Needed for header files being rewritten165 bool IsHeader;166 bool SilenceRewriteMacroWarning;167 bool GenerateLineInfo;168 bool objc_impl_method;169 170 bool DisableReplaceStmt;171 class DisableReplaceStmtScope {172 RewriteModernObjC &R;173 bool SavedValue;174 175 public:176 DisableReplaceStmtScope(RewriteModernObjC &R)177 : R(R), SavedValue(R.DisableReplaceStmt) {178 R.DisableReplaceStmt = true;179 }180 ~DisableReplaceStmtScope() {181 R.DisableReplaceStmt = SavedValue;182 }183 };184 void InitializeCommon(ASTContext &context);185 186 public:187 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;188 189 // Top Level Driver code.190 bool HandleTopLevelDecl(DeclGroupRef D) override {191 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {192 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) {193 if (!Class->isThisDeclarationADefinition()) {194 RewriteForwardClassDecl(D);195 break;196 } else {197 // Keep track of all interface declarations seen.198 ObjCInterfacesSeen.push_back(Class);199 break;200 }201 }202 203 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) {204 if (!Proto->isThisDeclarationADefinition()) {205 RewriteForwardProtocolDecl(D);206 break;207 }208 }209 210 if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I)) {211 // Under modern abi, we cannot translate body of the function212 // yet until all class extensions and its implementation is seen.213 // This is because they may introduce new bitfields which must go214 // into their grouping struct.215 if (FDecl->isThisDeclarationADefinition() &&216 // Not c functions defined inside an objc container.217 !FDecl->isTopLevelDeclInObjCContainer()) {218 FunctionDefinitionsSeen.push_back(FDecl);219 break;220 }221 }222 HandleTopLevelSingleDecl(*I);223 }224 return true;225 }226 227 void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override {228 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {229 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(*I)) {230 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))231 RewriteBlockPointerDecl(TD);232 else if (TD->getUnderlyingType()->isFunctionPointerType())233 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);234 else235 RewriteObjCQualifiedInterfaceTypes(TD);236 }237 }238 }239 240 void HandleTopLevelSingleDecl(Decl *D);241 void HandleDeclInMainFile(Decl *D);242 RewriteModernObjC(std::string inFile, std::unique_ptr<raw_ostream> OS,243 DiagnosticsEngine &D, const LangOptions &LOpts,244 bool silenceMacroWarn, bool LineInfo);245 246 ~RewriteModernObjC() override {}247 248 void HandleTranslationUnit(ASTContext &C) override;249 250 void ReplaceStmt(Stmt *Old, Stmt *New) {251 ReplaceStmtWithRange(Old, New, Old->getSourceRange());252 }253 254 void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {255 assert(Old != nullptr && New != nullptr && "Expected non-null Stmt's");256 257 Stmt *ReplacingStmt = ReplacedNodes[Old];258 if (ReplacingStmt)259 return; // We can't rewrite the same node twice.260 261 if (DisableReplaceStmt)262 return;263 264 // Measure the old text.265 int Size = Rewrite.getRangeSize(SrcRange);266 if (Size == -1) {267 Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)268 << Old->getSourceRange();269 return;270 }271 // Get the new text.272 std::string SStr;273 llvm::raw_string_ostream S(SStr);274 New->printPretty(S, nullptr, PrintingPolicy(LangOpts));275 276 // If replacement succeeded or warning disabled return with no warning.277 if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, SStr)) {278 ReplacedNodes[Old] = New;279 return;280 }281 if (SilenceRewriteMacroWarning)282 return;283 Diags.Report(Context->getFullLoc(Old->getBeginLoc()), RewriteFailedDiag)284 << Old->getSourceRange();285 }286 287 void InsertText(SourceLocation Loc, StringRef Str,288 bool InsertAfter = true) {289 // If insertion succeeded or warning disabled return with no warning.290 if (!Rewrite.InsertText(Loc, Str, InsertAfter) ||291 SilenceRewriteMacroWarning)292 return;293 294 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);295 }296 297 void ReplaceText(SourceLocation Start, unsigned OrigLength,298 StringRef Str) {299 // If removal succeeded or warning disabled return with no warning.300 if (!Rewrite.ReplaceText(Start, OrigLength, Str) ||301 SilenceRewriteMacroWarning)302 return;303 304 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);305 }306 307 // Syntactic Rewriting.308 void RewriteRecordBody(RecordDecl *RD);309 void RewriteInclude();310 void RewriteLineDirective(const Decl *D);311 void ConvertSourceLocationToLineDirective(SourceLocation Loc,312 std::string &LineString);313 void RewriteForwardClassDecl(DeclGroupRef D);314 void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG);315 void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,316 const std::string &typedefString);317 void RewriteImplementations();318 void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,319 ObjCImplementationDecl *IMD,320 ObjCCategoryImplDecl *CID);321 void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);322 void RewriteImplementationDecl(Decl *Dcl);323 void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,324 ObjCMethodDecl *MDecl, std::string &ResultStr);325 void RewriteTypeIntoString(QualType T, std::string &ResultStr,326 const FunctionType *&FPRetType);327 void RewriteByRefString(std::string &ResultStr, const std::string &Name,328 ValueDecl *VD, bool def=false);329 void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);330 void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);331 void RewriteForwardProtocolDecl(DeclGroupRef D);332 void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG);333 void RewriteMethodDeclaration(ObjCMethodDecl *Method);334 void RewriteProperty(ObjCPropertyDecl *prop);335 void RewriteFunctionDecl(FunctionDecl *FD);336 void RewriteBlockPointerType(std::string& Str, QualType Type);337 void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD);338 void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);339 void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);340 void RewriteTypeOfDecl(VarDecl *VD);341 void RewriteObjCQualifiedInterfaceTypes(Expr *E);342 343 std::string getIvarAccessString(ObjCIvarDecl *D);344 345 // Expression Rewriting.346 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);347 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);348 Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo);349 Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo);350 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);351 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);352 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);353 Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp);354 Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp);355 Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp);356 Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp);357 Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);358 Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);359 Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S);360 Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);361 Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);362 Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,363 SourceLocation OrigEnd);364 Stmt *RewriteBreakStmt(BreakStmt *S);365 Stmt *RewriteContinueStmt(ContinueStmt *S);366 void RewriteCastExpr(CStyleCastExpr *CE);367 void RewriteImplicitCastObjCExpr(CastExpr *IE);368 369 // Computes ivar bitfield group no.370 unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV);371 // Names field decl. for ivar bitfield group.372 void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result);373 // Names struct type for ivar bitfield group.374 void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result);375 // Names symbol for ivar bitfield group field offset.376 void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result);377 // Given an ivar bitfield, it builds (or finds) its group record type.378 QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV);379 QualType SynthesizeBitfieldGroupStructType(380 ObjCIvarDecl *IV,381 SmallVectorImpl<ObjCIvarDecl *> &IVars);382 383 // Block rewriting.384 void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);385 386 // Block specific rewrite rules.387 void RewriteBlockPointerDecl(NamedDecl *VD);388 void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl);389 Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD);390 Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);391 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);392 393 void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,394 std::string &Result);395 396 void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result);397 bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag,398 bool &IsNamedDefinition);399 void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,400 std::string &Result);401 402 bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result);403 404 void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,405 std::string &Result);406 407 void Initialize(ASTContext &context) override;408 409 // Misc. AST transformation routines. Sometimes they end up calling410 // rewriting routines on the new ASTs.411 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,412 ArrayRef<Expr *> Args,413 SourceLocation StartLoc=SourceLocation(),414 SourceLocation EndLoc=SourceLocation());415 416 Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,417 QualType returnType,418 SmallVectorImpl<QualType> &ArgTypes,419 SmallVectorImpl<Expr*> &MsgExprs,420 ObjCMethodDecl *Method);421 422 Stmt *SynthMessageExpr(ObjCMessageExpr *Exp,423 SourceLocation StartLoc=SourceLocation(),424 SourceLocation EndLoc=SourceLocation());425 426 void SynthCountByEnumWithState(std::string &buf);427 void SynthMsgSendFunctionDecl();428 void SynthMsgSendSuperFunctionDecl();429 void SynthMsgSendStretFunctionDecl();430 void SynthMsgSendFpretFunctionDecl();431 void SynthMsgSendSuperStretFunctionDecl();432 void SynthGetClassFunctionDecl();433 void SynthGetMetaClassFunctionDecl();434 void SynthGetSuperClassFunctionDecl();435 void SynthSelGetUidFunctionDecl();436 void SynthSuperConstructorFunctionDecl();437 438 // Rewriting metadata439 template<typename MethodIterator>440 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,441 MethodIterator MethodEnd,442 bool IsInstanceMethod,443 StringRef prefix,444 StringRef ClassName,445 std::string &Result);446 void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,447 std::string &Result);448 void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,449 std::string &Result);450 void RewriteClassSetupInitHook(std::string &Result);451 452 void RewriteMetaDataIntoBuffer(std::string &Result);453 void WriteImageInfo(std::string &Result);454 void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,455 std::string &Result);456 void RewriteCategorySetupInitHook(std::string &Result);457 458 // Rewriting ivar459 void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,460 std::string &Result);461 Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV);462 463 464 std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);465 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,466 StringRef funcName,467 const std::string &Tag);468 std::string SynthesizeBlockFunc(BlockExpr *CE, int i, StringRef funcName,469 const std::string &Tag);470 std::string SynthesizeBlockImpl(BlockExpr *CE, const std::string &Tag,471 const std::string &Desc);472 std::string SynthesizeBlockDescriptor(const std::string &DescTag,473 const std::string &ImplTag, int i,474 StringRef funcName, unsigned hasCopy);475 Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);476 void SynthesizeBlockLiterals(SourceLocation FunLocStart,477 StringRef FunName);478 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name);479 Stmt *SynthBlockInitExpr(BlockExpr *Exp,480 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs);481 482 // Misc. helper routines.483 QualType getProtocolType();484 void WarnAboutReturnGotoStmts(Stmt *S);485 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);486 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);487 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);488 489 bool IsDeclStmtInForeachHeader(DeclStmt *DS);490 void CollectBlockDeclRefInfo(BlockExpr *Exp);491 void GetBlockDeclRefExprs(Stmt *S);492 void GetInnerBlockDeclRefExprs(Stmt *S,493 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,494 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts);495 496 // We avoid calling Type::isBlockPointerType(), since it operates on the497 // canonical type. We only care if the top-level type is a closure pointer.498 bool isTopLevelBlockPointerType(QualType T) {499 return isa<BlockPointerType>(T);500 }501 502 /// convertBlockPointerToFunctionPointer - Converts a block-pointer type503 /// to a function pointer type and upon success, returns true; false504 /// otherwise.505 bool convertBlockPointerToFunctionPointer(QualType &T) {506 if (isTopLevelBlockPointerType(T)) {507 const auto *BPT = T->castAs<BlockPointerType>();508 T = Context->getPointerType(BPT->getPointeeType());509 return true;510 }511 return false;512 }513 514 bool convertObjCTypeToCStyleType(QualType &T);515 516 bool needToScanForQualifiers(QualType T);517 QualType getSuperStructType();518 QualType getConstantStringStructType();519 QualType convertFunctionTypeOfBlocks(const FunctionType *FT);520 521 void convertToUnqualifiedObjCType(QualType &T) {522 if (T->isObjCQualifiedIdType()) {523 bool isConst = T.isConstQualified();524 T = isConst ? Context->getObjCIdType().withConst()525 : Context->getObjCIdType();526 }527 else if (T->isObjCQualifiedClassType())528 T = Context->getObjCClassType();529 else if (T->isObjCObjectPointerType() &&530 T->getPointeeType()->isObjCQualifiedInterfaceType()) {531 if (const ObjCObjectPointerType * OBJPT =532 T->getAsObjCInterfacePointerType()) {533 const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType();534 T = QualType(IFaceT, 0);535 T = Context->getPointerType(T);536 }537 }538 }539 540 // FIXME: This predicate seems like it would be useful to add to ASTContext.541 bool isObjCType(QualType T) {542 if (!LangOpts.ObjC)543 return false;544 545 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();546 547 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||548 OCT == Context->getCanonicalType(Context->getObjCClassType()))549 return true;550 551 if (const PointerType *PT = OCT->getAs<PointerType>()) {552 if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||553 PT->getPointeeType()->isObjCQualifiedIdType())554 return true;555 }556 return false;557 }558 559 bool PointerTypeTakesAnyBlockArguments(QualType QT);560 bool PointerTypeTakesAnyObjCQualifiedType(QualType QT);561 void GetExtentOfArgList(const char *Name, const char *&LParen,562 const char *&RParen);563 564 void QuoteDoublequotes(std::string &From, std::string &To) {565 for (unsigned i = 0; i < From.length(); i++) {566 if (From[i] == '"')567 To += "\\\"";568 else569 To += From[i];570 }571 }572 573 QualType getSimpleFunctionType(QualType result,574 ArrayRef<QualType> args,575 bool variadic = false) {576 if (result == Context->getObjCInstanceType())577 result = Context->getObjCIdType();578 FunctionProtoType::ExtProtoInfo fpi;579 fpi.Variadic = variadic;580 return Context->getFunctionType(result, args, fpi);581 }582 583 // Helper function: create a CStyleCastExpr with trivial type source info.584 CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,585 CastKind Kind, Expr *E) {586 TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());587 return CStyleCastExpr::Create(*Ctx, Ty, VK_PRValue, Kind, E, nullptr,588 FPOptionsOverride(), TInfo,589 SourceLocation(), SourceLocation());590 }591 592 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const {593 const IdentifierInfo *II = &Context->Idents.get("load");594 Selector LoadSel = Context->Selectors.getSelector(0, &II);595 return OD->getClassMethod(LoadSel) != nullptr;596 }597 598 StringLiteral *getStringLiteral(StringRef Str) {599 QualType StrType = Context->getConstantArrayType(600 Context->CharTy, llvm::APInt(32, Str.size() + 1), nullptr,601 ArraySizeModifier::Normal, 0);602 return StringLiteral::Create(*Context, Str, StringLiteralKind::Ordinary,603 /*Pascal=*/false, StrType, SourceLocation());604 }605 };606} // end anonymous namespace607 608void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType,609 NamedDecl *D) {610 if (const FunctionProtoType *fproto611 = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) {612 for (const auto &I : fproto->param_types())613 if (isTopLevelBlockPointerType(I)) {614 // All the args are checked/rewritten. Don't call twice!615 RewriteBlockPointerDecl(D);616 break;617 }618 }619}620 621void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {622 const PointerType *PT = funcType->getAs<PointerType>();623 if (PT && PointerTypeTakesAnyBlockArguments(funcType))624 RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);625}626 627static bool IsHeaderFile(const std::string &Filename) {628 std::string::size_type DotPos = Filename.rfind('.');629 630 if (DotPos == std::string::npos) {631 // no file extension632 return false;633 }634 635 std::string Ext = Filename.substr(DotPos + 1);636 // C header: .h637 // C++ header: .hh or .H;638 return Ext == "h" || Ext == "hh" || Ext == "H";639}640 641RewriteModernObjC::RewriteModernObjC(std::string inFile,642 std::unique_ptr<raw_ostream> OS,643 DiagnosticsEngine &D,644 const LangOptions &LOpts,645 bool silenceMacroWarn, bool LineInfo)646 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(std::move(OS)),647 SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) {648 IsHeader = IsHeaderFile(inFile);649 RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,650 "rewriting sub-expression within a macro (may not be correct)");651 // FIXME. This should be an error. But if block is not called, it is OK. And it652 // may break including some headers.653 GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning,654 "rewriting block literal declared in global scope is not implemented");655 656 TryFinallyContainsReturnDiag = Diags.getCustomDiagID(657 DiagnosticsEngine::Warning,658 "rewriter doesn't support user-specified control flow semantics "659 "for @try/@finally (code may not execute properly)");660}661 662std::unique_ptr<ASTConsumer> clang::CreateModernObjCRewriter(663 const std::string &InFile, std::unique_ptr<raw_ostream> OS,664 DiagnosticsEngine &Diags, const LangOptions &LOpts,665 bool SilenceRewriteMacroWarning, bool LineInfo) {666 return std::make_unique<RewriteModernObjC>(InFile, std::move(OS), Diags,667 LOpts, SilenceRewriteMacroWarning,668 LineInfo);669}670 671void RewriteModernObjC::InitializeCommon(ASTContext &context) {672 Context = &context;673 SM = &Context->getSourceManager();674 TUDecl = Context->getTranslationUnitDecl();675 MsgSendFunctionDecl = nullptr;676 MsgSendSuperFunctionDecl = nullptr;677 MsgSendStretFunctionDecl = nullptr;678 MsgSendSuperStretFunctionDecl = nullptr;679 MsgSendFpretFunctionDecl = nullptr;680 GetClassFunctionDecl = nullptr;681 GetMetaClassFunctionDecl = nullptr;682 GetSuperClassFunctionDecl = nullptr;683 SelGetUidFunctionDecl = nullptr;684 CFStringFunctionDecl = nullptr;685 ConstantStringClassReference = nullptr;686 NSStringRecord = nullptr;687 CurMethodDef = nullptr;688 CurFunctionDef = nullptr;689 GlobalVarDecl = nullptr;690 GlobalConstructionExp = nullptr;691 SuperStructDecl = nullptr;692 ProtocolTypeDecl = nullptr;693 ConstantStringDecl = nullptr;694 BcLabelCount = 0;695 SuperConstructorFunctionDecl = nullptr;696 NumObjCStringLiterals = 0;697 PropParentMap = nullptr;698 CurrentBody = nullptr;699 DisableReplaceStmt = false;700 objc_impl_method = false;701 702 // Get the ID and start/end of the main file.703 MainFileID = SM->getMainFileID();704 llvm::MemoryBufferRef MainBuf = SM->getBufferOrFake(MainFileID);705 MainFileStart = MainBuf.getBufferStart();706 MainFileEnd = MainBuf.getBufferEnd();707 708 Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());709}710 711//===----------------------------------------------------------------------===//712// Top Level Driver Code713//===----------------------------------------------------------------------===//714 715void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) {716 if (Diags.hasErrorOccurred())717 return;718 719 // Two cases: either the decl could be in the main file, or it could be in a720 // #included file. If the former, rewrite it now. If the later, check to see721 // if we rewrote the #include/#import.722 SourceLocation Loc = D->getLocation();723 Loc = SM->getExpansionLoc(Loc);724 725 // If this is for a builtin, ignore it.726 if (Loc.isInvalid()) return;727 728 // Look for built-in declarations that we need to refer during the rewrite.729 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {730 RewriteFunctionDecl(FD);731 } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {732 // declared in <Foundation/NSString.h>733 if (FVD->getName() == "_NSConstantStringClassReference") {734 ConstantStringClassReference = FVD;735 return;736 }737 } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {738 RewriteCategoryDecl(CD);739 } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {740 if (PD->isThisDeclarationADefinition())741 RewriteProtocolDecl(PD);742 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {743 // Recurse into linkage specifications744 for (DeclContext::decl_iterator DI = LSD->decls_begin(),745 DIEnd = LSD->decls_end();746 DI != DIEnd; ) {747 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) {748 if (!IFace->isThisDeclarationADefinition()) {749 SmallVector<Decl *, 8> DG;750 SourceLocation StartLoc = IFace->getBeginLoc();751 do {752 if (isa<ObjCInterfaceDecl>(*DI) &&753 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() &&754 StartLoc == (*DI)->getBeginLoc())755 DG.push_back(*DI);756 else757 break;758 759 ++DI;760 } while (DI != DIEnd);761 RewriteForwardClassDecl(DG);762 continue;763 }764 else {765 // Keep track of all interface declarations seen.766 ObjCInterfacesSeen.push_back(IFace);767 ++DI;768 continue;769 }770 }771 772 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) {773 if (!Proto->isThisDeclarationADefinition()) {774 SmallVector<Decl *, 8> DG;775 SourceLocation StartLoc = Proto->getBeginLoc();776 do {777 if (isa<ObjCProtocolDecl>(*DI) &&778 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() &&779 StartLoc == (*DI)->getBeginLoc())780 DG.push_back(*DI);781 else782 break;783 784 ++DI;785 } while (DI != DIEnd);786 RewriteForwardProtocolDecl(DG);787 continue;788 }789 }790 791 HandleTopLevelSingleDecl(*DI);792 ++DI;793 }794 }795 // If we have a decl in the main file, see if we should rewrite it.796 if (SM->isWrittenInMainFile(Loc))797 return HandleDeclInMainFile(D);798}799 800//===----------------------------------------------------------------------===//801// Syntactic (non-AST) Rewriting Code802//===----------------------------------------------------------------------===//803 804void RewriteModernObjC::RewriteInclude() {805 SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);806 StringRef MainBuf = SM->getBufferData(MainFileID);807 const char *MainBufStart = MainBuf.begin();808 const char *MainBufEnd = MainBuf.end();809 size_t ImportLen = strlen("import");810 811 // Loop over the whole file, looking for includes.812 for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {813 if (*BufPtr == '#') {814 if (++BufPtr == MainBufEnd)815 return;816 while (*BufPtr == ' ' || *BufPtr == '\t')817 if (++BufPtr == MainBufEnd)818 return;819 if (!strncmp(BufPtr, "import", ImportLen)) {820 // replace import with include821 SourceLocation ImportLoc =822 LocStart.getLocWithOffset(BufPtr-MainBufStart);823 ReplaceText(ImportLoc, ImportLen, "include");824 BufPtr += ImportLen;825 }826 }827 }828}829 830static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl,831 ObjCIvarDecl *IvarDecl, std::string &Result) {832 Result += "OBJC_IVAR_$_";833 Result += IDecl->getName();834 Result += "$";835 Result += IvarDecl->getName();836}837 838std::string839RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) {840 const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface();841 842 // Build name of symbol holding ivar offset.843 std::string IvarOffsetName;844 if (D->isBitField())845 ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);846 else847 WriteInternalIvarName(ClassDecl, D, IvarOffsetName);848 849 std::string S = "(*(";850 QualType IvarT = D->getType();851 if (D->isBitField())852 IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);853 854 if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {855 RecordDecl *RD = IvarT->castAsCanonical<RecordType>()->getDecl();856 RD = RD->getDefinition();857 if (RD && !RD->getDeclName().getAsIdentifierInfo()) {858 // decltype(((Foo_IMPL*)0)->bar) *859 auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());860 // ivar in class extensions requires special treatment.861 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))862 CDecl = CatDecl->getClassInterface();863 std::string RecName = std::string(CDecl->getName());864 RecName += "_IMPL";865 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,866 SourceLocation(), SourceLocation(),867 &Context->Idents.get(RecName));868 QualType PtrStructIMPL =869 Context->getPointerType(Context->getCanonicalTagType(RD));870 unsigned UnsignedIntSize =871 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));872 Expr *Zero = IntegerLiteral::Create(*Context,873 llvm::APInt(UnsignedIntSize, 0),874 Context->UnsignedIntTy, SourceLocation());875 Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);876 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),877 Zero);878 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),879 SourceLocation(),880 &Context->Idents.get(D->getNameAsString()),881 IvarT, nullptr,882 /*BitWidth=*/nullptr, /*Mutable=*/true,883 ICIS_NoInit);884 MemberExpr *ME = MemberExpr::CreateImplicit(885 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);886 IvarT = Context->getDecltypeType(ME, ME->getType());887 }888 }889 convertObjCTypeToCStyleType(IvarT);890 QualType castT = Context->getPointerType(IvarT);891 std::string TypeString(castT.getAsString(Context->getPrintingPolicy()));892 S += TypeString;893 S += ")";894 895 // ((char *)self + IVAR_OFFSET_SYMBOL_NAME)896 S += "((char *)self + ";897 S += IvarOffsetName;898 S += "))";899 if (D->isBitField()) {900 S += ".";901 S += D->getNameAsString();902 }903 ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D);904 return S;905}906 907/// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not908/// been found in the class implementation. In this case, it must be synthesized.909static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP,910 ObjCPropertyDecl *PD,911 bool getter) {912 auto *OMD = IMP->getInstanceMethod(getter ? PD->getGetterName()913 : PD->getSetterName());914 return !OMD || OMD->isSynthesizedAccessorStub();915}916 917void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,918 ObjCImplementationDecl *IMD,919 ObjCCategoryImplDecl *CID) {920 static bool objcGetPropertyDefined = false;921 static bool objcSetPropertyDefined = false;922 SourceLocation startGetterSetterLoc;923 924 if (PID->getBeginLoc().isValid()) {925 SourceLocation startLoc = PID->getBeginLoc();926 InsertText(startLoc, "// ");927 const char *startBuf = SM->getCharacterData(startLoc);928 assert((*startBuf == '@') && "bogus @synthesize location");929 const char *semiBuf = strchr(startBuf, ';');930 assert((*semiBuf == ';') && "@synthesize: can't find ';'");931 startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1);932 } else933 startGetterSetterLoc = IMD ? IMD->getEndLoc() : CID->getEndLoc();934 935 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)936 return; // FIXME: is this correct?937 938 // Generate the 'getter' function.939 ObjCPropertyDecl *PD = PID->getPropertyDecl();940 ObjCIvarDecl *OID = PID->getPropertyIvarDecl();941 assert(IMD && OID && "Synthesized ivars must be attached to @implementation");942 943 unsigned Attributes = PD->getPropertyAttributes();944 if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) {945 bool GenGetProperty =946 !(Attributes & ObjCPropertyAttribute::kind_nonatomic) &&947 (Attributes & (ObjCPropertyAttribute::kind_retain |948 ObjCPropertyAttribute::kind_copy));949 std::string Getr;950 if (GenGetProperty && !objcGetPropertyDefined) {951 objcGetPropertyDefined = true;952 // FIXME. Is this attribute correct in all cases?953 Getr = "\nextern \"C\" __declspec(dllimport) "954 "id objc_getProperty(id, SEL, long, bool);\n";955 }956 RewriteObjCMethodDecl(OID->getContainingInterface(),957 PID->getGetterMethodDecl(), Getr);958 Getr += "{ ";959 // Synthesize an explicit cast to gain access to the ivar.960 // See objc-act.c:objc_synthesize_new_getter() for details.961 if (GenGetProperty) {962 // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1)963 Getr += "typedef ";964 const FunctionType *FPRetType = nullptr;965 RewriteTypeIntoString(PID->getGetterMethodDecl()->getReturnType(), Getr,966 FPRetType);967 Getr += " _TYPE";968 if (FPRetType) {969 Getr += ")"; // close the precedence "scope" for "*".970 971 // Now, emit the argument types (if any).972 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){973 Getr += "(";974 for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {975 if (i) Getr += ", ";976 std::string ParamStr =977 FT->getParamType(i).getAsString(Context->getPrintingPolicy());978 Getr += ParamStr;979 }980 if (FT->isVariadic()) {981 if (FT->getNumParams())982 Getr += ", ";983 Getr += "...";984 }985 Getr += ")";986 } else987 Getr += "()";988 }989 Getr += ";\n";990 Getr += "return (_TYPE)";991 Getr += "objc_getProperty(self, _cmd, ";992 RewriteIvarOffsetComputation(OID, Getr);993 Getr += ", 1)";994 }995 else996 Getr += "return " + getIvarAccessString(OID);997 Getr += "; }";998 InsertText(startGetterSetterLoc, Getr);999 }1000 1001 if (PD->isReadOnly() ||1002 !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/))1003 return;1004 1005 // Generate the 'setter' function.1006 std::string Setr;1007 bool GenSetProperty = Attributes & (ObjCPropertyAttribute::kind_retain |1008 ObjCPropertyAttribute::kind_copy);1009 if (GenSetProperty && !objcSetPropertyDefined) {1010 objcSetPropertyDefined = true;1011 // FIXME. Is this attribute correct in all cases?1012 Setr = "\nextern \"C\" __declspec(dllimport) "1013 "void objc_setProperty (id, SEL, long, id, bool, bool);\n";1014 }1015 1016 RewriteObjCMethodDecl(OID->getContainingInterface(),1017 PID->getSetterMethodDecl(), Setr);1018 Setr += "{ ";1019 // Synthesize an explicit cast to initialize the ivar.1020 // See objc-act.c:objc_synthesize_new_setter() for details.1021 if (GenSetProperty) {1022 Setr += "objc_setProperty (self, _cmd, ";1023 RewriteIvarOffsetComputation(OID, Setr);1024 Setr += ", (id)";1025 Setr += PD->getName();1026 Setr += ", ";1027 if (Attributes & ObjCPropertyAttribute::kind_nonatomic)1028 Setr += "0, ";1029 else1030 Setr += "1, ";1031 if (Attributes & ObjCPropertyAttribute::kind_copy)1032 Setr += "1)";1033 else1034 Setr += "0)";1035 }1036 else {1037 Setr += getIvarAccessString(OID) + " = ";1038 Setr += PD->getName();1039 }1040 Setr += "; }\n";1041 InsertText(startGetterSetterLoc, Setr);1042}1043 1044static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl,1045 std::string &typedefString) {1046 typedefString += "\n#ifndef _REWRITER_typedef_";1047 typedefString += ForwardDecl->getNameAsString();1048 typedefString += "\n";1049 typedefString += "#define _REWRITER_typedef_";1050 typedefString += ForwardDecl->getNameAsString();1051 typedefString += "\n";1052 typedefString += "typedef struct objc_object ";1053 typedefString += ForwardDecl->getNameAsString();1054 // typedef struct { } _objc_exc_Classname;1055 typedefString += ";\ntypedef struct {} _objc_exc_";1056 typedefString += ForwardDecl->getNameAsString();1057 typedefString += ";\n#endif\n";1058}1059 1060void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl,1061 const std::string &typedefString) {1062 SourceLocation startLoc = ClassDecl->getBeginLoc();1063 const char *startBuf = SM->getCharacterData(startLoc);1064 const char *semiPtr = strchr(startBuf, ';');1065 // Replace the @class with typedefs corresponding to the classes.1066 ReplaceText(startLoc, semiPtr-startBuf+1, typedefString);1067}1068 1069void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) {1070 std::string typedefString;1071 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) {1072 if (ObjCInterfaceDecl *ForwardDecl = dyn_cast<ObjCInterfaceDecl>(*I)) {1073 if (I == D.begin()) {1074 // Translate to typedef's that forward reference structs with the same name1075 // as the class. As a convenience, we include the original declaration1076 // as a comment.1077 typedefString += "// @class ";1078 typedefString += ForwardDecl->getNameAsString();1079 typedefString += ";";1080 }1081 RewriteOneForwardClassDecl(ForwardDecl, typedefString);1082 }1083 else1084 HandleTopLevelSingleDecl(*I);1085 }1086 DeclGroupRef::iterator I = D.begin();1087 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString);1088}1089 1090void RewriteModernObjC::RewriteForwardClassDecl(1091 const SmallVectorImpl<Decl *> &D) {1092 std::string typedefString;1093 for (unsigned i = 0; i < D.size(); i++) {1094 ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]);1095 if (i == 0) {1096 typedefString += "// @class ";1097 typedefString += ForwardDecl->getNameAsString();1098 typedefString += ";";1099 }1100 RewriteOneForwardClassDecl(ForwardDecl, typedefString);1101 }1102 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString);1103}1104 1105void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {1106 // When method is a synthesized one, such as a getter/setter there is1107 // nothing to rewrite.1108 if (Method->isImplicit())1109 return;1110 SourceLocation LocStart = Method->getBeginLoc();1111 SourceLocation LocEnd = Method->getEndLoc();1112 1113 if (SM->getExpansionLineNumber(LocEnd) >1114 SM->getExpansionLineNumber(LocStart)) {1115 InsertText(LocStart, "#if 0\n");1116 ReplaceText(LocEnd, 1, ";\n#endif\n");1117 } else {1118 InsertText(LocStart, "// ");1119 }1120}1121 1122void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) {1123 SourceLocation Loc = prop->getAtLoc();1124 1125 ReplaceText(Loc, 0, "// ");1126 // FIXME: handle properties that are declared across multiple lines.1127}1128 1129void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {1130 SourceLocation LocStart = CatDecl->getBeginLoc();1131 1132 // FIXME: handle category headers that are declared across multiple lines.1133 if (CatDecl->getIvarRBraceLoc().isValid()) {1134 ReplaceText(LocStart, 1, "/** ");1135 ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ ");1136 }1137 else {1138 ReplaceText(LocStart, 0, "// ");1139 }1140 1141 for (auto *I : CatDecl->instance_properties())1142 RewriteProperty(I);1143 1144 for (auto *I : CatDecl->instance_methods())1145 RewriteMethodDeclaration(I);1146 for (auto *I : CatDecl->class_methods())1147 RewriteMethodDeclaration(I);1148 1149 // Lastly, comment out the @end.1150 ReplaceText(CatDecl->getAtEndRange().getBegin(),1151 strlen("@end"), "/* @end */\n");1152}1153 1154void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {1155 SourceLocation LocStart = PDecl->getBeginLoc();1156 assert(PDecl->isThisDeclarationADefinition());1157 1158 // FIXME: handle protocol headers that are declared across multiple lines.1159 ReplaceText(LocStart, 0, "// ");1160 1161 for (auto *I : PDecl->instance_methods())1162 RewriteMethodDeclaration(I);1163 for (auto *I : PDecl->class_methods())1164 RewriteMethodDeclaration(I);1165 for (auto *I : PDecl->instance_properties())1166 RewriteProperty(I);1167 1168 // Lastly, comment out the @end.1169 SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();1170 ReplaceText(LocEnd, strlen("@end"), "/* @end */\n");1171 1172 // Must comment out @optional/@required1173 const char *startBuf = SM->getCharacterData(LocStart);1174 const char *endBuf = SM->getCharacterData(LocEnd);1175 for (const char *p = startBuf; p < endBuf; p++) {1176 if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {1177 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1178 ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */");1179 1180 }1181 else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {1182 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf);1183 ReplaceText(OptionalLoc, strlen("@required"), "/* @required */");1184 1185 }1186 }1187}1188 1189void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) {1190 SourceLocation LocStart = (*D.begin())->getBeginLoc();1191 if (LocStart.isInvalid())1192 llvm_unreachable("Invalid SourceLocation");1193 // FIXME: handle forward protocol that are declared across multiple lines.1194 ReplaceText(LocStart, 0, "// ");1195}1196 1197void1198RewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) {1199 SourceLocation LocStart = DG[0]->getBeginLoc();1200 if (LocStart.isInvalid())1201 llvm_unreachable("Invalid SourceLocation");1202 // FIXME: handle forward protocol that are declared across multiple lines.1203 ReplaceText(LocStart, 0, "// ");1204}1205 1206void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr,1207 const FunctionType *&FPRetType) {1208 if (T->isObjCQualifiedIdType())1209 ResultStr += "id";1210 else if (T->isFunctionPointerType() ||1211 T->isBlockPointerType()) {1212 // needs special handling, since pointer-to-functions have special1213 // syntax (where a decaration models use).1214 QualType retType = T;1215 QualType PointeeTy;1216 if (const PointerType* PT = retType->getAs<PointerType>())1217 PointeeTy = PT->getPointeeType();1218 else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())1219 PointeeTy = BPT->getPointeeType();1220 if ((FPRetType = PointeeTy->getAs<FunctionType>())) {1221 ResultStr +=1222 FPRetType->getReturnType().getAsString(Context->getPrintingPolicy());1223 ResultStr += "(*";1224 }1225 } else1226 ResultStr += T.getAsString(Context->getPrintingPolicy());1227}1228 1229void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl,1230 ObjCMethodDecl *OMD,1231 std::string &ResultStr) {1232 //fprintf(stderr,"In RewriteObjCMethodDecl\n");1233 const FunctionType *FPRetType = nullptr;1234 ResultStr += "\nstatic ";1235 RewriteTypeIntoString(OMD->getReturnType(), ResultStr, FPRetType);1236 ResultStr += " ";1237 1238 // Unique method name1239 std::string NameStr;1240 1241 if (OMD->isInstanceMethod())1242 NameStr += "_I_";1243 else1244 NameStr += "_C_";1245 1246 NameStr += IDecl->getNameAsString();1247 NameStr += "_";1248 1249 if (ObjCCategoryImplDecl *CID =1250 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {1251 NameStr += CID->getNameAsString();1252 NameStr += "_";1253 }1254 // Append selector names, replacing ':' with '_'1255 {1256 std::string selString = OMD->getSelector().getAsString();1257 int len = selString.size();1258 for (int i = 0; i < len; i++)1259 if (selString[i] == ':')1260 selString[i] = '_';1261 NameStr += selString;1262 }1263 // Remember this name for metadata emission1264 MethodInternalNames[OMD] = NameStr;1265 ResultStr += NameStr;1266 1267 // Rewrite arguments1268 ResultStr += "(";1269 1270 // invisible arguments1271 if (OMD->isInstanceMethod()) {1272 QualType selfTy = Context->getObjCInterfaceType(IDecl);1273 selfTy = Context->getPointerType(selfTy);1274 if (!LangOpts.MicrosoftExt) {1275 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl)))1276 ResultStr += "struct ";1277 }1278 // When rewriting for Microsoft, explicitly omit the structure name.1279 ResultStr += IDecl->getNameAsString();1280 ResultStr += " *";1281 }1282 else1283 ResultStr += Context->getObjCClassType().getAsString(1284 Context->getPrintingPolicy());1285 1286 ResultStr += " self, ";1287 ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy());1288 ResultStr += " _cmd";1289 1290 // Method arguments.1291 for (const auto *PDecl : OMD->parameters()) {1292 ResultStr += ", ";1293 if (PDecl->getType()->isObjCQualifiedIdType()) {1294 ResultStr += "id ";1295 ResultStr += PDecl->getNameAsString();1296 } else {1297 std::string Name = PDecl->getNameAsString();1298 QualType QT = PDecl->getType();1299 // Make sure we convert "t (^)(...)" to "t (*)(...)".1300 (void)convertBlockPointerToFunctionPointer(QT);1301 QT.getAsStringInternal(Name, Context->getPrintingPolicy());1302 ResultStr += Name;1303 }1304 }1305 if (OMD->isVariadic())1306 ResultStr += ", ...";1307 ResultStr += ") ";1308 1309 if (FPRetType) {1310 ResultStr += ")"; // close the precedence "scope" for "*".1311 1312 // Now, emit the argument types (if any).1313 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {1314 ResultStr += "(";1315 for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i) {1316 if (i) ResultStr += ", ";1317 std::string ParamStr =1318 FT->getParamType(i).getAsString(Context->getPrintingPolicy());1319 ResultStr += ParamStr;1320 }1321 if (FT->isVariadic()) {1322 if (FT->getNumParams())1323 ResultStr += ", ";1324 ResultStr += "...";1325 }1326 ResultStr += ")";1327 } else {1328 ResultStr += "()";1329 }1330 }1331}1332 1333void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) {1334 ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);1335 ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);1336 assert((IMD || CID) && "Unknown implementation type");1337 1338 if (IMD) {1339 if (IMD->getIvarRBraceLoc().isValid()) {1340 ReplaceText(IMD->getBeginLoc(), 1, "/** ");1341 ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ ");1342 }1343 else {1344 InsertText(IMD->getBeginLoc(), "// ");1345 }1346 }1347 else1348 InsertText(CID->getBeginLoc(), "// ");1349 1350 for (auto *OMD : IMD ? IMD->instance_methods() : CID->instance_methods()) {1351 if (!OMD->getBody())1352 continue;1353 std::string ResultStr;1354 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1355 SourceLocation LocStart = OMD->getBeginLoc();1356 SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();1357 1358 const char *startBuf = SM->getCharacterData(LocStart);1359 const char *endBuf = SM->getCharacterData(LocEnd);1360 ReplaceText(LocStart, endBuf-startBuf, ResultStr);1361 }1362 1363 for (auto *OMD : IMD ? IMD->class_methods() : CID->class_methods()) {1364 if (!OMD->getBody())1365 continue;1366 std::string ResultStr;1367 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr);1368 SourceLocation LocStart = OMD->getBeginLoc();1369 SourceLocation LocEnd = OMD->getCompoundBody()->getBeginLoc();1370 1371 const char *startBuf = SM->getCharacterData(LocStart);1372 const char *endBuf = SM->getCharacterData(LocEnd);1373 ReplaceText(LocStart, endBuf-startBuf, ResultStr);1374 }1375 for (auto *I : IMD ? IMD->property_impls() : CID->property_impls())1376 RewritePropertyImplDecl(I, IMD, CID);1377 1378 InsertText(IMD ? IMD->getEndLoc() : CID->getEndLoc(), "// ");1379}1380 1381void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {1382 // Do not synthesize more than once.1383 if (ObjCSynthesizedStructs.count(ClassDecl))1384 return;1385 // Make sure super class's are written before current class is written.1386 ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass();1387 while (SuperClass) {1388 RewriteInterfaceDecl(SuperClass);1389 SuperClass = SuperClass->getSuperClass();1390 }1391 std::string ResultStr;1392 if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) {1393 // we haven't seen a forward decl - generate a typedef.1394 RewriteOneForwardClassDecl(ClassDecl, ResultStr);1395 RewriteIvarOffsetSymbols(ClassDecl, ResultStr);1396 1397 RewriteObjCInternalStruct(ClassDecl, ResultStr);1398 // Mark this typedef as having been written into its c++ equivalent.1399 ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl());1400 1401 for (auto *I : ClassDecl->instance_properties())1402 RewriteProperty(I);1403 for (auto *I : ClassDecl->instance_methods())1404 RewriteMethodDeclaration(I);1405 for (auto *I : ClassDecl->class_methods())1406 RewriteMethodDeclaration(I);1407 1408 // Lastly, comment out the @end.1409 ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"),1410 "/* @end */\n");1411 }1412}1413 1414Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) {1415 SourceRange OldRange = PseudoOp->getSourceRange();1416 1417 // We just magically know some things about the structure of this1418 // expression.1419 ObjCMessageExpr *OldMsg =1420 cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr(1421 PseudoOp->getNumSemanticExprs() - 1));1422 1423 // Because the rewriter doesn't allow us to rewrite rewritten code,1424 // we need to suppress rewriting the sub-statements.1425 Expr *Base;1426 SmallVector<Expr*, 2> Args;1427 {1428 DisableReplaceStmtScope S(*this);1429 1430 // Rebuild the base expression if we have one.1431 Base = nullptr;1432 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1433 Base = OldMsg->getInstanceReceiver();1434 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1435 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1436 }1437 1438 unsigned numArgs = OldMsg->getNumArgs();1439 for (unsigned i = 0; i < numArgs; i++) {1440 Expr *Arg = OldMsg->getArg(i);1441 if (isa<OpaqueValueExpr>(Arg))1442 Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();1443 Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));1444 Args.push_back(Arg);1445 }1446 }1447 1448 // TODO: avoid this copy.1449 SmallVector<SourceLocation, 1> SelLocs;1450 OldMsg->getSelectorLocs(SelLocs);1451 1452 ObjCMessageExpr *NewMsg = nullptr;1453 switch (OldMsg->getReceiverKind()) {1454 case ObjCMessageExpr::Class:1455 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1456 OldMsg->getValueKind(),1457 OldMsg->getLeftLoc(),1458 OldMsg->getClassReceiverTypeInfo(),1459 OldMsg->getSelector(),1460 SelLocs,1461 OldMsg->getMethodDecl(),1462 Args,1463 OldMsg->getRightLoc(),1464 OldMsg->isImplicit());1465 break;1466 1467 case ObjCMessageExpr::Instance:1468 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1469 OldMsg->getValueKind(),1470 OldMsg->getLeftLoc(),1471 Base,1472 OldMsg->getSelector(),1473 SelLocs,1474 OldMsg->getMethodDecl(),1475 Args,1476 OldMsg->getRightLoc(),1477 OldMsg->isImplicit());1478 break;1479 1480 case ObjCMessageExpr::SuperClass:1481 case ObjCMessageExpr::SuperInstance:1482 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1483 OldMsg->getValueKind(),1484 OldMsg->getLeftLoc(),1485 OldMsg->getSuperLoc(),1486 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1487 OldMsg->getSuperType(),1488 OldMsg->getSelector(),1489 SelLocs,1490 OldMsg->getMethodDecl(),1491 Args,1492 OldMsg->getRightLoc(),1493 OldMsg->isImplicit());1494 break;1495 }1496 1497 Stmt *Replacement = SynthMessageExpr(NewMsg);1498 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1499 return Replacement;1500}1501 1502Stmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) {1503 SourceRange OldRange = PseudoOp->getSourceRange();1504 1505 // We just magically know some things about the structure of this1506 // expression.1507 ObjCMessageExpr *OldMsg =1508 cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit());1509 1510 // Because the rewriter doesn't allow us to rewrite rewritten code,1511 // we need to suppress rewriting the sub-statements.1512 Expr *Base = nullptr;1513 SmallVector<Expr*, 1> Args;1514 {1515 DisableReplaceStmtScope S(*this);1516 // Rebuild the base expression if we have one.1517 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) {1518 Base = OldMsg->getInstanceReceiver();1519 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr();1520 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base));1521 }1522 unsigned numArgs = OldMsg->getNumArgs();1523 for (unsigned i = 0; i < numArgs; i++) {1524 Expr *Arg = OldMsg->getArg(i);1525 if (isa<OpaqueValueExpr>(Arg))1526 Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr();1527 Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg));1528 Args.push_back(Arg);1529 }1530 }1531 1532 // Intentionally empty.1533 SmallVector<SourceLocation, 1> SelLocs;1534 1535 ObjCMessageExpr *NewMsg = nullptr;1536 switch (OldMsg->getReceiverKind()) {1537 case ObjCMessageExpr::Class:1538 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1539 OldMsg->getValueKind(),1540 OldMsg->getLeftLoc(),1541 OldMsg->getClassReceiverTypeInfo(),1542 OldMsg->getSelector(),1543 SelLocs,1544 OldMsg->getMethodDecl(),1545 Args,1546 OldMsg->getRightLoc(),1547 OldMsg->isImplicit());1548 break;1549 1550 case ObjCMessageExpr::Instance:1551 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1552 OldMsg->getValueKind(),1553 OldMsg->getLeftLoc(),1554 Base,1555 OldMsg->getSelector(),1556 SelLocs,1557 OldMsg->getMethodDecl(),1558 Args,1559 OldMsg->getRightLoc(),1560 OldMsg->isImplicit());1561 break;1562 1563 case ObjCMessageExpr::SuperClass:1564 case ObjCMessageExpr::SuperInstance:1565 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(),1566 OldMsg->getValueKind(),1567 OldMsg->getLeftLoc(),1568 OldMsg->getSuperLoc(),1569 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance,1570 OldMsg->getSuperType(),1571 OldMsg->getSelector(),1572 SelLocs,1573 OldMsg->getMethodDecl(),1574 Args,1575 OldMsg->getRightLoc(),1576 OldMsg->isImplicit());1577 break;1578 }1579 1580 Stmt *Replacement = SynthMessageExpr(NewMsg);1581 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange);1582 return Replacement;1583}1584 1585/// SynthCountByEnumWithState - To print:1586/// ((NSUInteger (*)1587/// (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))1588/// (void *)objc_msgSend)((id)l_collection,1589/// sel_registerName(1590/// "countByEnumeratingWithState:objects:count:"),1591/// &enumState,1592/// (id *)__rw_items, (NSUInteger)16)1593///1594void RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) {1595 buf += "((_WIN_NSUInteger (*) (id, SEL, struct __objcFastEnumerationState *, "1596 "id *, _WIN_NSUInteger))(void *)objc_msgSend)";1597 buf += "\n\t\t";1598 buf += "((id)l_collection,\n\t\t";1599 buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";1600 buf += "\n\t\t";1601 buf += "&enumState, "1602 "(id *)__rw_items, (_WIN_NSUInteger)16)";1603}1604 1605/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach1606/// statement to exit to its outer synthesized loop.1607///1608Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) {1609 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1610 return S;1611 // replace break with goto __break_label1612 std::string buf;1613 1614 SourceLocation startLoc = S->getBeginLoc();1615 buf = "goto __break_label_";1616 buf += utostr(ObjCBcLabelNo.back());1617 ReplaceText(startLoc, strlen("break"), buf);1618 1619 return nullptr;1620}1621 1622void RewriteModernObjC::ConvertSourceLocationToLineDirective(1623 SourceLocation Loc,1624 std::string &LineString) {1625 if (Loc.isFileID() && GenerateLineInfo) {1626 LineString += "\n#line ";1627 PresumedLoc PLoc = SM->getPresumedLoc(Loc);1628 LineString += utostr(PLoc.getLine());1629 LineString += " \"";1630 LineString += Lexer::Stringify(PLoc.getFilename());1631 LineString += "\"\n";1632 }1633}1634 1635/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach1636/// statement to continue with its inner synthesized loop.1637///1638Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) {1639 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))1640 return S;1641 // replace continue with goto __continue_label1642 std::string buf;1643 1644 SourceLocation startLoc = S->getBeginLoc();1645 buf = "goto __continue_label_";1646 buf += utostr(ObjCBcLabelNo.back());1647 ReplaceText(startLoc, strlen("continue"), buf);1648 1649 return nullptr;1650}1651 1652/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.1653/// It rewrites:1654/// for ( type elem in collection) { stmts; }1655 1656/// Into:1657/// {1658/// type elem;1659/// struct __objcFastEnumerationState enumState = { 0 };1660/// id __rw_items[16];1661/// id l_collection = (id)collection;1662/// NSUInteger limit = [l_collection countByEnumeratingWithState:&enumState1663/// objects:__rw_items count:16];1664/// if (limit) {1665/// unsigned long startMutations = *enumState.mutationsPtr;1666/// do {1667/// unsigned long counter = 0;1668/// do {1669/// if (startMutations != *enumState.mutationsPtr)1670/// objc_enumerationMutation(l_collection);1671/// elem = (type)enumState.itemsPtr[counter++];1672/// stmts;1673/// __continue_label: ;1674/// } while (counter < limit);1675/// } while ((limit = [l_collection countByEnumeratingWithState:&enumState1676/// objects:__rw_items count:16]));1677/// elem = nil;1678/// __break_label: ;1679/// }1680/// else1681/// elem = nil;1682/// }1683///1684Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,1685 SourceLocation OrigEnd) {1686 assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");1687 assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&1688 "ObjCForCollectionStmt Statement stack mismatch");1689 assert(!ObjCBcLabelNo.empty() &&1690 "ObjCForCollectionStmt - Label No stack empty");1691 1692 SourceLocation startLoc = S->getBeginLoc();1693 const char *startBuf = SM->getCharacterData(startLoc);1694 StringRef elementName;1695 std::string elementTypeAsString;1696 std::string buf;1697 // line directive first.1698 SourceLocation ForEachLoc = S->getForLoc();1699 ConvertSourceLocationToLineDirective(ForEachLoc, buf);1700 buf += "{\n\t";1701 if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {1702 // type elem;1703 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());1704 QualType ElementType = cast<ValueDecl>(D)->getType();1705 if (ElementType->isObjCQualifiedIdType() ||1706 ElementType->isObjCQualifiedInterfaceType())1707 // Simply use 'id' for all qualified types.1708 elementTypeAsString = "id";1709 else1710 elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy());1711 buf += elementTypeAsString;1712 buf += " ";1713 elementName = D->getName();1714 buf += elementName;1715 buf += ";\n\t";1716 }1717 else {1718 DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());1719 elementName = DR->getDecl()->getName();1720 ValueDecl *VD = DR->getDecl();1721 if (VD->getType()->isObjCQualifiedIdType() ||1722 VD->getType()->isObjCQualifiedInterfaceType())1723 // Simply use 'id' for all qualified types.1724 elementTypeAsString = "id";1725 else1726 elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy());1727 }1728 1729 // struct __objcFastEnumerationState enumState = { 0 };1730 buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";1731 // id __rw_items[16];1732 buf += "id __rw_items[16];\n\t";1733 // id l_collection = (id)1734 buf += "id l_collection = (id)";1735 // Find start location of 'collection' the hard way!1736 const char *startCollectionBuf = startBuf;1737 startCollectionBuf += 3; // skip 'for'1738 startCollectionBuf = strchr(startCollectionBuf, '(');1739 startCollectionBuf++; // skip '('1740 // find 'in' and skip it.1741 while (*startCollectionBuf != ' ' ||1742 *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||1743 (*(startCollectionBuf+3) != ' ' &&1744 *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))1745 startCollectionBuf++;1746 startCollectionBuf += 3;1747 1748 // Replace: "for (type element in" with string constructed thus far.1749 ReplaceText(startLoc, startCollectionBuf - startBuf, buf);1750 // Replace ')' in for '(' type elem in collection ')' with ';'1751 SourceLocation rightParenLoc = S->getRParenLoc();1752 const char *rparenBuf = SM->getCharacterData(rightParenLoc);1753 SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf);1754 buf = ";\n\t";1755 1756 // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState1757 // objects:__rw_items count:16];1758 // which is synthesized into:1759 // NSUInteger limit =1760 // ((NSUInteger (*)1761 // (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger))1762 // (void *)objc_msgSend)((id)l_collection,1763 // sel_registerName(1764 // "countByEnumeratingWithState:objects:count:"),1765 // (struct __objcFastEnumerationState *)&state,1766 // (id *)__rw_items, (NSUInteger)16);1767 buf += "_WIN_NSUInteger limit =\n\t\t";1768 SynthCountByEnumWithState(buf);1769 buf += ";\n\t";1770 /// if (limit) {1771 /// unsigned long startMutations = *enumState.mutationsPtr;1772 /// do {1773 /// unsigned long counter = 0;1774 /// do {1775 /// if (startMutations != *enumState.mutationsPtr)1776 /// objc_enumerationMutation(l_collection);1777 /// elem = (type)enumState.itemsPtr[counter++];1778 buf += "if (limit) {\n\t";1779 buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";1780 buf += "do {\n\t\t";1781 buf += "unsigned long counter = 0;\n\t\t";1782 buf += "do {\n\t\t\t";1783 buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";1784 buf += "objc_enumerationMutation(l_collection);\n\t\t\t";1785 buf += elementName;1786 buf += " = (";1787 buf += elementTypeAsString;1788 buf += ")enumState.itemsPtr[counter++];";1789 // Replace ')' in for '(' type elem in collection ')' with all of these.1790 ReplaceText(lparenLoc, 1, buf);1791 1792 /// __continue_label: ;1793 /// } while (counter < limit);1794 /// } while ((limit = [l_collection countByEnumeratingWithState:&enumState1795 /// objects:__rw_items count:16]));1796 /// elem = nil;1797 /// __break_label: ;1798 /// }1799 /// else1800 /// elem = nil;1801 /// }1802 ///1803 buf = ";\n\t";1804 buf += "__continue_label_";1805 buf += utostr(ObjCBcLabelNo.back());1806 buf += ": ;";1807 buf += "\n\t\t";1808 buf += "} while (counter < limit);\n\t";1809 buf += "} while ((limit = ";1810 SynthCountByEnumWithState(buf);1811 buf += "));\n\t";1812 buf += elementName;1813 buf += " = ((";1814 buf += elementTypeAsString;1815 buf += ")0);\n\t";1816 buf += "__break_label_";1817 buf += utostr(ObjCBcLabelNo.back());1818 buf += ": ;\n\t";1819 buf += "}\n\t";1820 buf += "else\n\t\t";1821 buf += elementName;1822 buf += " = ((";1823 buf += elementTypeAsString;1824 buf += ")0);\n\t";1825 buf += "}\n";1826 1827 // Insert all these *after* the statement body.1828 // FIXME: If this should support Obj-C++, support CXXTryStmt1829 if (isa<CompoundStmt>(S->getBody())) {1830 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1);1831 InsertText(endBodyLoc, buf);1832 } else {1833 /* Need to treat single statements specially. For example:1834 *1835 * for (A *a in b) if (stuff()) break;1836 * for (A *a in b) xxxyy;1837 *1838 * The following code simply scans ahead to the semi to find the actual end.1839 */1840 const char *stmtBuf = SM->getCharacterData(OrigEnd);1841 const char *semiBuf = strchr(stmtBuf, ';');1842 assert(semiBuf && "Can't find ';'");1843 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1);1844 InsertText(endBodyLoc, buf);1845 }1846 Stmts.pop_back();1847 ObjCBcLabelNo.pop_back();1848 return nullptr;1849}1850 1851static void Write_RethrowObject(std::string &buf) {1852 buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n";1853 buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n";1854 buf += "\tid rethrow;\n";1855 buf += "\t} _fin_force_rethow(_rethrow);";1856}1857 1858/// RewriteObjCSynchronizedStmt -1859/// This routine rewrites @synchronized(expr) stmt;1860/// into:1861/// objc_sync_enter(expr);1862/// @try stmt @finally { objc_sync_exit(expr); }1863///1864Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {1865 // Get the start location and compute the semi location.1866 SourceLocation startLoc = S->getBeginLoc();1867 const char *startBuf = SM->getCharacterData(startLoc);1868 1869 assert((*startBuf == '@') && "bogus @synchronized location");1870 1871 std::string buf;1872 SourceLocation SynchLoc = S->getAtSynchronizedLoc();1873 ConvertSourceLocationToLineDirective(SynchLoc, buf);1874 buf += "{ id _rethrow = 0; id _sync_obj = (id)";1875 1876 const char *lparenBuf = startBuf;1877 while (*lparenBuf != '(') lparenBuf++;1878 ReplaceText(startLoc, lparenBuf-startBuf+1, buf);1879 1880 buf = "; objc_sync_enter(_sync_obj);\n";1881 buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}";1882 buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}";1883 buf += "\n\tid sync_exit;";1884 buf += "\n\t} _sync_exit(_sync_obj);\n";1885 1886 // We can't use S->getSynchExpr()->getEndLoc() to find the end location, since1887 // the sync expression is typically a message expression that's already1888 // been rewritten! (which implies the SourceLocation's are invalid).1889 SourceLocation RParenExprLoc = S->getSynchBody()->getBeginLoc();1890 const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc);1891 while (*RParenExprLocBuf != ')') RParenExprLocBuf--;1892 RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf);1893 1894 SourceLocation LBranceLoc = S->getSynchBody()->getBeginLoc();1895 const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc);1896 assert (*LBraceLocBuf == '{');1897 ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf);1898 1899 SourceLocation startRBraceLoc = S->getSynchBody()->getEndLoc();1900 assert((*SM->getCharacterData(startRBraceLoc) == '}') &&1901 "bogus @synchronized block");1902 1903 buf = "} catch (id e) {_rethrow = e;}\n";1904 Write_RethrowObject(buf);1905 buf += "}\n";1906 buf += "}\n";1907 1908 ReplaceText(startRBraceLoc, 1, buf);1909 1910 return nullptr;1911}1912 1913void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S)1914{1915 // Perform a bottom up traversal of all children.1916 for (Stmt *SubStmt : S->children())1917 if (SubStmt)1918 WarnAboutReturnGotoStmts(SubStmt);1919 1920 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {1921 Diags.Report(Context->getFullLoc(S->getBeginLoc()),1922 TryFinallyContainsReturnDiag);1923 }1924}1925 1926Stmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) {1927 SourceLocation startLoc = S->getAtLoc();1928 ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */");1929 ReplaceText(S->getSubStmt()->getBeginLoc(), 1,1930 "{ __AtAutoreleasePool __autoreleasepool; ");1931 1932 return nullptr;1933}1934 1935Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {1936 ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt();1937 bool noCatch = S->getNumCatchStmts() == 0;1938 std::string buf;1939 SourceLocation TryLocation = S->getAtTryLoc();1940 ConvertSourceLocationToLineDirective(TryLocation, buf);1941 1942 if (finalStmt) {1943 if (noCatch)1944 buf += "{ id volatile _rethrow = 0;\n";1945 else {1946 buf += "{ id volatile _rethrow = 0;\ntry {\n";1947 }1948 }1949 // Get the start location and compute the semi location.1950 SourceLocation startLoc = S->getBeginLoc();1951 const char *startBuf = SM->getCharacterData(startLoc);1952 1953 assert((*startBuf == '@') && "bogus @try location");1954 if (finalStmt)1955 ReplaceText(startLoc, 1, buf);1956 else1957 // @try -> try1958 ReplaceText(startLoc, 1, "");1959 1960 for (ObjCAtCatchStmt *Catch : S->catch_stmts()) {1961 VarDecl *catchDecl = Catch->getCatchParamDecl();1962 1963 startLoc = Catch->getBeginLoc();1964 bool AtRemoved = false;1965 if (catchDecl) {1966 QualType t = catchDecl->getType();1967 if (const ObjCObjectPointerType *Ptr =1968 t->getAs<ObjCObjectPointerType>()) {1969 // Should be a pointer to a class.1970 ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface();1971 if (IDecl) {1972 std::string Result;1973 ConvertSourceLocationToLineDirective(Catch->getBeginLoc(), Result);1974 1975 startBuf = SM->getCharacterData(startLoc);1976 assert((*startBuf == '@') && "bogus @catch location");1977 SourceLocation rParenLoc = Catch->getRParenLoc();1978 const char *rParenBuf = SM->getCharacterData(rParenLoc);1979 1980 // _objc_exc_Foo *_e as argument to catch.1981 Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString();1982 Result += " *_"; Result += catchDecl->getNameAsString();1983 Result += ")";1984 ReplaceText(startLoc, rParenBuf-startBuf+1, Result);1985 // Foo *e = (Foo *)_e;1986 Result.clear();1987 Result = "{ ";1988 Result += IDecl->getNameAsString();1989 Result += " *"; Result += catchDecl->getNameAsString();1990 Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)";1991 Result += "_"; Result += catchDecl->getNameAsString();1992 1993 Result += "; ";1994 SourceLocation lBraceLoc = Catch->getCatchBody()->getBeginLoc();1995 ReplaceText(lBraceLoc, 1, Result);1996 AtRemoved = true;1997 }1998 }1999 }2000 if (!AtRemoved)2001 // @catch -> catch2002 ReplaceText(startLoc, 1, "");2003 2004 }2005 if (finalStmt) {2006 buf.clear();2007 SourceLocation FinallyLoc = finalStmt->getBeginLoc();2008 2009 if (noCatch) {2010 ConvertSourceLocationToLineDirective(FinallyLoc, buf);2011 buf += "catch (id e) {_rethrow = e;}\n";2012 }2013 else {2014 buf += "}\n";2015 ConvertSourceLocationToLineDirective(FinallyLoc, buf);2016 buf += "catch (id e) {_rethrow = e;}\n";2017 }2018 2019 SourceLocation startFinalLoc = finalStmt->getBeginLoc();2020 ReplaceText(startFinalLoc, 8, buf);2021 Stmt *body = finalStmt->getFinallyBody();2022 SourceLocation startFinalBodyLoc = body->getBeginLoc();2023 buf.clear();2024 Write_RethrowObject(buf);2025 ReplaceText(startFinalBodyLoc, 1, buf);2026 2027 SourceLocation endFinalBodyLoc = body->getEndLoc();2028 ReplaceText(endFinalBodyLoc, 1, "}\n}");2029 // Now check for any return/continue/go statements within the @try.2030 WarnAboutReturnGotoStmts(S->getTryBody());2031 }2032 2033 return nullptr;2034}2035 2036// This can't be done with ReplaceStmt(S, ThrowExpr), since2037// the throw expression is typically a message expression that's already2038// been rewritten! (which implies the SourceLocation's are invalid).2039Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {2040 // Get the start location and compute the semi location.2041 SourceLocation startLoc = S->getBeginLoc();2042 const char *startBuf = SM->getCharacterData(startLoc);2043 2044 assert((*startBuf == '@') && "bogus @throw location");2045 2046 std::string buf;2047 /* void objc_exception_throw(id) __attribute__((noreturn)); */2048 if (S->getThrowExpr())2049 buf = "objc_exception_throw(";2050 else2051 buf = "throw";2052 2053 // handle "@ throw" correctly.2054 const char *wBuf = strchr(startBuf, 'w');2055 assert((*wBuf == 'w') && "@throw: can't find 'w'");2056 ReplaceText(startLoc, wBuf-startBuf+1, buf);2057 2058 SourceLocation endLoc = S->getEndLoc();2059 const char *endBuf = SM->getCharacterData(endLoc);2060 const char *semiBuf = strchr(endBuf, ';');2061 assert((*semiBuf == ';') && "@throw: can't find ';'");2062 SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf);2063 if (S->getThrowExpr())2064 ReplaceText(semiLoc, 1, ");");2065 return nullptr;2066}2067 2068Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {2069 // Create a new string expression.2070 std::string StrEncoding;2071 Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);2072 Expr *Replacement = getStringLiteral(StrEncoding);2073 ReplaceStmt(Exp, Replacement);2074 2075 // Replace this subexpr in the parent.2076 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2077 return Replacement;2078}2079 2080Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {2081 if (!SelGetUidFunctionDecl)2082 SynthSelGetUidFunctionDecl();2083 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");2084 // Create a call to sel_registerName("selName").2085 SmallVector<Expr*, 8> SelExprs;2086 SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));2087 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2088 SelExprs);2089 ReplaceStmt(Exp, SelExp);2090 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2091 return SelExp;2092}2093 2094CallExpr *2095RewriteModernObjC::SynthesizeCallToFunctionDecl(FunctionDecl *FD,2096 ArrayRef<Expr *> Args,2097 SourceLocation StartLoc,2098 SourceLocation EndLoc) {2099 // Get the type, we will need to reference it in a couple spots.2100 QualType msgSendType = FD->getType();2101 2102 // Create a reference to the objc_msgSend() declaration.2103 DeclRefExpr *DRE = new (Context) DeclRefExpr(*Context, FD, false, msgSendType,2104 VK_LValue, SourceLocation());2105 2106 // Now, we cast the reference to a pointer to the objc_msgSend type.2107 QualType pToFunc = Context->getPointerType(msgSendType);2108 ImplicitCastExpr *ICE =2109 ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay,2110 DRE, nullptr, VK_PRValue, FPOptionsOverride());2111 2112 const auto *FT = msgSendType->castAs<FunctionType>();2113 CallExpr *Exp =2114 CallExpr::Create(*Context, ICE, Args, FT->getCallResultType(*Context),2115 VK_PRValue, EndLoc, FPOptionsOverride());2116 return Exp;2117}2118 2119static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,2120 const char *&startRef, const char *&endRef) {2121 while (startBuf < endBuf) {2122 if (*startBuf == '<')2123 startRef = startBuf; // mark the start.2124 if (*startBuf == '>') {2125 if (startRef && *startRef == '<') {2126 endRef = startBuf; // mark the end.2127 return true;2128 }2129 return false;2130 }2131 startBuf++;2132 }2133 return false;2134}2135 2136static void scanToNextArgument(const char *&argRef) {2137 int angle = 0;2138 while (*argRef != ')' && (*argRef != ',' || angle > 0)) {2139 if (*argRef == '<')2140 angle++;2141 else if (*argRef == '>')2142 angle--;2143 argRef++;2144 }2145 assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");2146}2147 2148bool RewriteModernObjC::needToScanForQualifiers(QualType T) {2149 if (T->isObjCQualifiedIdType())2150 return true;2151 if (const PointerType *PT = T->getAs<PointerType>()) {2152 if (PT->getPointeeType()->isObjCQualifiedIdType())2153 return true;2154 }2155 if (T->isObjCObjectPointerType()) {2156 T = T->getPointeeType();2157 return T->isObjCQualifiedInterfaceType();2158 }2159 if (T->isArrayType()) {2160 QualType ElemTy = Context->getBaseElementType(T);2161 return needToScanForQualifiers(ElemTy);2162 }2163 return false;2164}2165 2166void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {2167 QualType Type = E->getType();2168 if (needToScanForQualifiers(Type)) {2169 SourceLocation Loc, EndLoc;2170 2171 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {2172 Loc = ECE->getLParenLoc();2173 EndLoc = ECE->getRParenLoc();2174 } else {2175 Loc = E->getBeginLoc();2176 EndLoc = E->getEndLoc();2177 }2178 // This will defend against trying to rewrite synthesized expressions.2179 if (Loc.isInvalid() || EndLoc.isInvalid())2180 return;2181 2182 const char *startBuf = SM->getCharacterData(Loc);2183 const char *endBuf = SM->getCharacterData(EndLoc);2184 const char *startRef = nullptr, *endRef = nullptr;2185 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2186 // Get the locations of the startRef, endRef.2187 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf);2188 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1);2189 // Comment out the protocol references.2190 InsertText(LessLoc, "/*");2191 InsertText(GreaterLoc, "*/");2192 }2193 }2194}2195 2196void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {2197 SourceLocation Loc;2198 QualType Type;2199 const FunctionProtoType *proto = nullptr;2200 if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {2201 Loc = VD->getLocation();2202 Type = VD->getType();2203 }2204 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {2205 Loc = FD->getLocation();2206 // Check for ObjC 'id' and class types that have been adorned with protocol2207 // information (id<p>, C<p>*). The protocol references need to be rewritten!2208 const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2209 assert(funcType && "missing function type");2210 proto = dyn_cast<FunctionProtoType>(funcType);2211 if (!proto)2212 return;2213 Type = proto->getReturnType();2214 }2215 else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {2216 Loc = FD->getLocation();2217 Type = FD->getType();2218 }2219 else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) {2220 Loc = TD->getLocation();2221 Type = TD->getUnderlyingType();2222 }2223 else2224 return;2225 2226 if (needToScanForQualifiers(Type)) {2227 // Since types are unique, we need to scan the buffer.2228 2229 const char *endBuf = SM->getCharacterData(Loc);2230 const char *startBuf = endBuf;2231 while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)2232 startBuf--; // scan backward (from the decl location) for return type.2233 const char *startRef = nullptr, *endRef = nullptr;2234 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2235 // Get the locations of the startRef, endRef.2236 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf);2237 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1);2238 // Comment out the protocol references.2239 InsertText(LessLoc, "/*");2240 InsertText(GreaterLoc, "*/");2241 }2242 }2243 if (!proto)2244 return; // most likely, was a variable2245 // Now check arguments.2246 const char *startBuf = SM->getCharacterData(Loc);2247 const char *startFuncBuf = startBuf;2248 for (unsigned i = 0; i < proto->getNumParams(); i++) {2249 if (needToScanForQualifiers(proto->getParamType(i))) {2250 // Since types are unique, we need to scan the buffer.2251 2252 const char *endBuf = startBuf;2253 // scan forward (from the decl location) for argument types.2254 scanToNextArgument(endBuf);2255 const char *startRef = nullptr, *endRef = nullptr;2256 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {2257 // Get the locations of the startRef, endRef.2258 SourceLocation LessLoc =2259 Loc.getLocWithOffset(startRef-startFuncBuf);2260 SourceLocation GreaterLoc =2261 Loc.getLocWithOffset(endRef-startFuncBuf+1);2262 // Comment out the protocol references.2263 InsertText(LessLoc, "/*");2264 InsertText(GreaterLoc, "*/");2265 }2266 startBuf = ++endBuf;2267 }2268 else {2269 // If the function name is derived from a macro expansion, then the2270 // argument buffer will not follow the name. Need to speak with Chris.2271 while (*startBuf && *startBuf != ')' && *startBuf != ',')2272 startBuf++; // scan forward (from the decl location) for argument types.2273 startBuf++;2274 }2275 }2276}2277 2278void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) {2279 QualType QT = ND->getType();2280 const Type* TypePtr = QT->getAs<Type>();2281 if (!isa<TypeOfExprType>(TypePtr))2282 return;2283 while (isa<TypeOfExprType>(TypePtr)) {2284 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);2285 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();2286 TypePtr = QT->getAs<Type>();2287 }2288 // FIXME. This will not work for multiple declarators; as in:2289 // __typeof__(a) b,c,d;2290 std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy()));2291 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();2292 const char *startBuf = SM->getCharacterData(DeclLoc);2293 if (ND->getInit()) {2294 std::string Name(ND->getNameAsString());2295 TypeAsString += " " + Name + " = ";2296 Expr *E = ND->getInit();2297 SourceLocation startLoc;2298 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))2299 startLoc = ECE->getLParenLoc();2300 else2301 startLoc = E->getBeginLoc();2302 startLoc = SM->getExpansionLoc(startLoc);2303 const char *endBuf = SM->getCharacterData(startLoc);2304 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2305 }2306 else {2307 SourceLocation X = ND->getEndLoc();2308 X = SM->getExpansionLoc(X);2309 const char *endBuf = SM->getCharacterData(X);2310 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString);2311 }2312}2313 2314// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);2315void RewriteModernObjC::SynthSelGetUidFunctionDecl() {2316 IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");2317 SmallVector<QualType, 16> ArgTys;2318 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2319 QualType getFuncType =2320 getSimpleFunctionType(Context->getObjCSelType(), ArgTys);2321 SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2322 SourceLocation(),2323 SourceLocation(),2324 SelGetUidIdent, getFuncType,2325 nullptr, SC_Extern);2326}2327 2328void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) {2329 // declared in <objc/objc.h>2330 if (FD->getIdentifier() &&2331 FD->getName() == "sel_registerName") {2332 SelGetUidFunctionDecl = FD;2333 return;2334 }2335 RewriteObjCQualifiedInterfaceTypes(FD);2336}2337 2338void RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) {2339 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2340 const char *argPtr = TypeString.c_str();2341 if (!strchr(argPtr, '^')) {2342 Str += TypeString;2343 return;2344 }2345 while (*argPtr) {2346 Str += (*argPtr == '^' ? '*' : *argPtr);2347 argPtr++;2348 }2349}2350 2351// FIXME. Consolidate this routine with RewriteBlockPointerType.2352void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str,2353 ValueDecl *VD) {2354 QualType Type = VD->getType();2355 std::string TypeString(Type.getAsString(Context->getPrintingPolicy()));2356 const char *argPtr = TypeString.c_str();2357 int paren = 0;2358 while (*argPtr) {2359 switch (*argPtr) {2360 case '(':2361 Str += *argPtr;2362 paren++;2363 break;2364 case ')':2365 Str += *argPtr;2366 paren--;2367 break;2368 case '^':2369 Str += '*';2370 if (paren == 1)2371 Str += VD->getNameAsString();2372 break;2373 default:2374 Str += *argPtr;2375 break;2376 }2377 argPtr++;2378 }2379}2380 2381void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {2382 SourceLocation FunLocStart = FD->getTypeSpecStartLoc();2383 const FunctionType *funcType = FD->getType()->getAs<FunctionType>();2384 const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);2385 if (!proto)2386 return;2387 QualType Type = proto->getReturnType();2388 std::string FdStr = Type.getAsString(Context->getPrintingPolicy());2389 FdStr += " ";2390 FdStr += FD->getName();2391 FdStr += "(";2392 unsigned numArgs = proto->getNumParams();2393 for (unsigned i = 0; i < numArgs; i++) {2394 QualType ArgType = proto->getParamType(i);2395 RewriteBlockPointerType(FdStr, ArgType);2396 if (i+1 < numArgs)2397 FdStr += ", ";2398 }2399 if (FD->isVariadic()) {2400 FdStr += (numArgs > 0) ? ", ...);\n" : "...);\n";2401 }2402 else2403 FdStr += ");\n";2404 InsertText(FunLocStart, FdStr);2405}2406 2407// SynthSuperConstructorFunctionDecl - id __rw_objc_super(id obj, id super);2408void RewriteModernObjC::SynthSuperConstructorFunctionDecl() {2409 if (SuperConstructorFunctionDecl)2410 return;2411 IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");2412 SmallVector<QualType, 16> ArgTys;2413 QualType argT = Context->getObjCIdType();2414 assert(!argT.isNull() && "Can't find 'id' type");2415 ArgTys.push_back(argT);2416 ArgTys.push_back(argT);2417 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2418 ArgTys);2419 SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2420 SourceLocation(),2421 SourceLocation(),2422 msgSendIdent, msgSendType,2423 nullptr, SC_Extern);2424}2425 2426// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);2427void RewriteModernObjC::SynthMsgSendFunctionDecl() {2428 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");2429 SmallVector<QualType, 16> ArgTys;2430 QualType argT = Context->getObjCIdType();2431 assert(!argT.isNull() && "Can't find 'id' type");2432 ArgTys.push_back(argT);2433 argT = Context->getObjCSelType();2434 assert(!argT.isNull() && "Can't find 'SEL' type");2435 ArgTys.push_back(argT);2436 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2437 ArgTys, /*variadic=*/true);2438 MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2439 SourceLocation(),2440 SourceLocation(),2441 msgSendIdent, msgSendType, nullptr,2442 SC_Extern);2443}2444 2445// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void);2446void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() {2447 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");2448 SmallVector<QualType, 2> ArgTys;2449 ArgTys.push_back(Context->VoidTy);2450 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2451 ArgTys, /*variadic=*/true);2452 MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2453 SourceLocation(),2454 SourceLocation(),2455 msgSendIdent, msgSendType,2456 nullptr, SC_Extern);2457}2458 2459// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);2460void RewriteModernObjC::SynthMsgSendStretFunctionDecl() {2461 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");2462 SmallVector<QualType, 16> ArgTys;2463 QualType argT = Context->getObjCIdType();2464 assert(!argT.isNull() && "Can't find 'id' type");2465 ArgTys.push_back(argT);2466 argT = Context->getObjCSelType();2467 assert(!argT.isNull() && "Can't find 'SEL' type");2468 ArgTys.push_back(argT);2469 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2470 ArgTys, /*variadic=*/true);2471 MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2472 SourceLocation(),2473 SourceLocation(),2474 msgSendIdent, msgSendType,2475 nullptr, SC_Extern);2476}2477 2478// SynthMsgSendSuperStretFunctionDecl -2479// id objc_msgSendSuper_stret(void);2480void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() {2481 IdentifierInfo *msgSendIdent =2482 &Context->Idents.get("objc_msgSendSuper_stret");2483 SmallVector<QualType, 2> ArgTys;2484 ArgTys.push_back(Context->VoidTy);2485 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(),2486 ArgTys, /*variadic=*/true);2487 MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2488 SourceLocation(),2489 SourceLocation(),2490 msgSendIdent,2491 msgSendType, nullptr,2492 SC_Extern);2493}2494 2495// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);2496void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() {2497 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");2498 SmallVector<QualType, 16> ArgTys;2499 QualType argT = Context->getObjCIdType();2500 assert(!argT.isNull() && "Can't find 'id' type");2501 ArgTys.push_back(argT);2502 argT = Context->getObjCSelType();2503 assert(!argT.isNull() && "Can't find 'SEL' type");2504 ArgTys.push_back(argT);2505 QualType msgSendType = getSimpleFunctionType(Context->DoubleTy,2506 ArgTys, /*variadic=*/true);2507 MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2508 SourceLocation(),2509 SourceLocation(),2510 msgSendIdent, msgSendType,2511 nullptr, SC_Extern);2512}2513 2514// SynthGetClassFunctionDecl - Class objc_getClass(const char *name);2515void RewriteModernObjC::SynthGetClassFunctionDecl() {2516 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");2517 SmallVector<QualType, 16> ArgTys;2518 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2519 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2520 ArgTys);2521 GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2522 SourceLocation(),2523 SourceLocation(),2524 getClassIdent, getClassType,2525 nullptr, SC_Extern);2526}2527 2528// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls);2529void RewriteModernObjC::SynthGetSuperClassFunctionDecl() {2530 IdentifierInfo *getSuperClassIdent =2531 &Context->Idents.get("class_getSuperclass");2532 SmallVector<QualType, 16> ArgTys;2533 ArgTys.push_back(Context->getObjCClassType());2534 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2535 ArgTys);2536 GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2537 SourceLocation(),2538 SourceLocation(),2539 getSuperClassIdent,2540 getClassType, nullptr,2541 SC_Extern);2542}2543 2544// SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name);2545void RewriteModernObjC::SynthGetMetaClassFunctionDecl() {2546 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");2547 SmallVector<QualType, 16> ArgTys;2548 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));2549 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(),2550 ArgTys);2551 GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,2552 SourceLocation(),2553 SourceLocation(),2554 getClassIdent, getClassType,2555 nullptr, SC_Extern);2556}2557 2558Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {2559 assert (Exp != nullptr && "Expected non-null ObjCStringLiteral");2560 QualType strType = getConstantStringStructType();2561 2562 std::string S = "__NSConstantStringImpl_";2563 2564 std::string tmpName = InFileName;2565 unsigned i;2566 for (i=0; i < tmpName.length(); i++) {2567 char c = tmpName.at(i);2568 // replace any non-alphanumeric characters with '_'.2569 if (!isAlphanumeric(c))2570 tmpName[i] = '_';2571 }2572 S += tmpName;2573 S += "_";2574 S += utostr(NumObjCStringLiterals++);2575 2576 Preamble += "static __NSConstantStringImpl " + S;2577 Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";2578 Preamble += "0x000007c8,"; // utf8_str2579 // The pretty printer for StringLiteral handles escape characters properly.2580 std::string prettyBufS;2581 llvm::raw_string_ostream prettyBuf(prettyBufS);2582 Exp->getString()->printPretty(prettyBuf, nullptr, PrintingPolicy(LangOpts));2583 Preamble += prettyBufS;2584 Preamble += ",";2585 Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";2586 2587 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),2588 SourceLocation(), &Context->Idents.get(S),2589 strType, nullptr, SC_Static);2590 DeclRefExpr *DRE = new (Context)2591 DeclRefExpr(*Context, NewVD, false, strType, VK_LValue, SourceLocation());2592 Expr *Unop = UnaryOperator::Create(2593 const_cast<ASTContext &>(*Context), DRE, UO_AddrOf,2594 Context->getPointerType(DRE->getType()), VK_PRValue, OK_Ordinary,2595 SourceLocation(), false, FPOptionsOverride());2596 // cast to NSConstantString *2597 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),2598 CK_CPointerToObjCPointerCast, Unop);2599 ReplaceStmt(Exp, cast);2600 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.2601 return cast;2602}2603 2604Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) {2605 unsigned IntSize =2606 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));2607 2608 Expr *FlagExp = IntegerLiteral::Create(*Context,2609 llvm::APInt(IntSize, Exp->getValue()),2610 Context->IntTy, Exp->getLocation());2611 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy,2612 CK_BitCast, FlagExp);2613 ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(),2614 cast);2615 ReplaceStmt(Exp, PE);2616 return PE;2617}2618 2619Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) {2620 // synthesize declaration of helper functions needed in this routine.2621 if (!SelGetUidFunctionDecl)2622 SynthSelGetUidFunctionDecl();2623 // use objc_msgSend() for all.2624 if (!MsgSendFunctionDecl)2625 SynthMsgSendFunctionDecl();2626 if (!GetClassFunctionDecl)2627 SynthGetClassFunctionDecl();2628 2629 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2630 SourceLocation StartLoc = Exp->getBeginLoc();2631 SourceLocation EndLoc = Exp->getEndLoc();2632 2633 // Synthesize a call to objc_msgSend().2634 SmallVector<Expr*, 4> MsgExprs;2635 SmallVector<Expr*, 4> ClsExprs;2636 2637 // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument.2638 ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod();2639 ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface();2640 2641 IdentifierInfo *clsName = BoxingClass->getIdentifier();2642 ClsExprs.push_back(getStringLiteral(clsName->getName()));2643 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2644 StartLoc, EndLoc);2645 MsgExprs.push_back(Cls);2646 2647 // Create a call to sel_registerName("<BoxingMethod>:"), etc.2648 // it will be the 2nd argument.2649 SmallVector<Expr*, 4> SelExprs;2650 SelExprs.push_back(2651 getStringLiteral(BoxingMethod->getSelector().getAsString()));2652 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2653 SelExprs, StartLoc, EndLoc);2654 MsgExprs.push_back(SelExp);2655 2656 // User provided sub-expression is the 3rd, and last, argument.2657 Expr *subExpr = Exp->getSubExpr();2658 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) {2659 QualType type = ICE->getType();2660 const Expr *SubExpr = ICE->IgnoreParenImpCasts();2661 CastKind CK = CK_BitCast;2662 if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType())2663 CK = CK_IntegralToBoolean;2664 subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr);2665 }2666 MsgExprs.push_back(subExpr);2667 2668 SmallVector<QualType, 4> ArgTypes;2669 ArgTypes.push_back(Context->getObjCClassType());2670 ArgTypes.push_back(Context->getObjCSelType());2671 for (const auto PI : BoxingMethod->parameters())2672 ArgTypes.push_back(PI->getType());2673 2674 QualType returnType = Exp->getType();2675 // Get the type, we will need to reference it in a couple spots.2676 QualType msgSendType = MsgSendFlavor->getType();2677 2678 // Create a reference to the objc_msgSend() declaration.2679 DeclRefExpr *DRE = new (Context) DeclRefExpr(2680 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());2681 2682 CastExpr *cast = NoTypeInfoCStyleCastExpr(2683 Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);2684 2685 // Now do the "normal" pointer to function cast.2686 QualType castType =2687 getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic());2688 castType = Context->getPointerType(castType);2689 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2690 cast);2691 2692 // Don't forget the parens to enforce the proper binding.2693 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);2694 2695 auto *FT = msgSendType->castAs<FunctionType>();2696 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2697 VK_PRValue, EndLoc, FPOptionsOverride());2698 ReplaceStmt(Exp, CE);2699 return CE;2700}2701 2702Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) {2703 // synthesize declaration of helper functions needed in this routine.2704 if (!SelGetUidFunctionDecl)2705 SynthSelGetUidFunctionDecl();2706 // use objc_msgSend() for all.2707 if (!MsgSendFunctionDecl)2708 SynthMsgSendFunctionDecl();2709 if (!GetClassFunctionDecl)2710 SynthGetClassFunctionDecl();2711 2712 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2713 SourceLocation StartLoc = Exp->getBeginLoc();2714 SourceLocation EndLoc = Exp->getEndLoc();2715 2716 // Build the expression: __NSContainer_literal(int, ...).arr2717 QualType IntQT = Context->IntTy;2718 QualType NSArrayFType =2719 getSimpleFunctionType(Context->VoidTy, IntQT, true);2720 std::string NSArrayFName("__NSContainer_literal");2721 FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName);2722 DeclRefExpr *NSArrayDRE = new (Context) DeclRefExpr(2723 *Context, NSArrayFD, false, NSArrayFType, VK_PRValue, SourceLocation());2724 2725 SmallVector<Expr*, 16> InitExprs;2726 unsigned NumElements = Exp->getNumElements();2727 unsigned UnsignedIntSize =2728 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));2729 Expr *count = IntegerLiteral::Create(*Context,2730 llvm::APInt(UnsignedIntSize, NumElements),2731 Context->UnsignedIntTy, SourceLocation());2732 InitExprs.push_back(count);2733 for (unsigned i = 0; i < NumElements; i++)2734 InitExprs.push_back(Exp->getElement(i));2735 Expr *NSArrayCallExpr =2736 CallExpr::Create(*Context, NSArrayDRE, InitExprs, NSArrayFType, VK_LValue,2737 SourceLocation(), FPOptionsOverride());2738 2739 FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),2740 SourceLocation(),2741 &Context->Idents.get("arr"),2742 Context->getPointerType(Context->VoidPtrTy),2743 nullptr, /*BitWidth=*/nullptr,2744 /*Mutable=*/true, ICIS_NoInit);2745 MemberExpr *ArrayLiteralME =2746 MemberExpr::CreateImplicit(*Context, NSArrayCallExpr, false, ARRFD,2747 ARRFD->getType(), VK_LValue, OK_Ordinary);2748 QualType ConstIdT = Context->getObjCIdType().withConst();2749 CStyleCastExpr * ArrayLiteralObjects =2750 NoTypeInfoCStyleCastExpr(Context,2751 Context->getPointerType(ConstIdT),2752 CK_BitCast,2753 ArrayLiteralME);2754 2755 // Synthesize a call to objc_msgSend().2756 SmallVector<Expr*, 32> MsgExprs;2757 SmallVector<Expr*, 4> ClsExprs;2758 QualType expType = Exp->getType();2759 2760 // Create a call to objc_getClass("NSArray"). It will be th 1st argument.2761 ObjCInterfaceDecl *Class =2762 expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();2763 2764 IdentifierInfo *clsName = Class->getIdentifier();2765 ClsExprs.push_back(getStringLiteral(clsName->getName()));2766 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2767 StartLoc, EndLoc);2768 MsgExprs.push_back(Cls);2769 2770 // Create a call to sel_registerName("arrayWithObjects:count:").2771 // it will be the 2nd argument.2772 SmallVector<Expr*, 4> SelExprs;2773 ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod();2774 SelExprs.push_back(2775 getStringLiteral(ArrayMethod->getSelector().getAsString()));2776 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2777 SelExprs, StartLoc, EndLoc);2778 MsgExprs.push_back(SelExp);2779 2780 // (const id [])objects2781 MsgExprs.push_back(ArrayLiteralObjects);2782 2783 // (NSUInteger)cnt2784 Expr *cnt = IntegerLiteral::Create(*Context,2785 llvm::APInt(UnsignedIntSize, NumElements),2786 Context->UnsignedIntTy, SourceLocation());2787 MsgExprs.push_back(cnt);2788 2789 SmallVector<QualType, 4> ArgTypes;2790 ArgTypes.push_back(Context->getObjCClassType());2791 ArgTypes.push_back(Context->getObjCSelType());2792 for (const auto *PI : ArrayMethod->parameters())2793 ArgTypes.push_back(PI->getType());2794 2795 QualType returnType = Exp->getType();2796 // Get the type, we will need to reference it in a couple spots.2797 QualType msgSendType = MsgSendFlavor->getType();2798 2799 // Create a reference to the objc_msgSend() declaration.2800 DeclRefExpr *DRE = new (Context) DeclRefExpr(2801 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());2802 2803 CastExpr *cast = NoTypeInfoCStyleCastExpr(2804 Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);2805 2806 // Now do the "normal" pointer to function cast.2807 QualType castType =2808 getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic());2809 castType = Context->getPointerType(castType);2810 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2811 cast);2812 2813 // Don't forget the parens to enforce the proper binding.2814 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);2815 2816 const FunctionType *FT = msgSendType->castAs<FunctionType>();2817 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2818 VK_PRValue, EndLoc, FPOptionsOverride());2819 ReplaceStmt(Exp, CE);2820 return CE;2821}2822 2823Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) {2824 // synthesize declaration of helper functions needed in this routine.2825 if (!SelGetUidFunctionDecl)2826 SynthSelGetUidFunctionDecl();2827 // use objc_msgSend() for all.2828 if (!MsgSendFunctionDecl)2829 SynthMsgSendFunctionDecl();2830 if (!GetClassFunctionDecl)2831 SynthGetClassFunctionDecl();2832 2833 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;2834 SourceLocation StartLoc = Exp->getBeginLoc();2835 SourceLocation EndLoc = Exp->getEndLoc();2836 2837 // Build the expression: __NSContainer_literal(int, ...).arr2838 QualType IntQT = Context->IntTy;2839 QualType NSDictFType =2840 getSimpleFunctionType(Context->VoidTy, IntQT, true);2841 std::string NSDictFName("__NSContainer_literal");2842 FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName);2843 DeclRefExpr *NSDictDRE = new (Context) DeclRefExpr(2844 *Context, NSDictFD, false, NSDictFType, VK_PRValue, SourceLocation());2845 2846 SmallVector<Expr*, 16> KeyExprs;2847 SmallVector<Expr*, 16> ValueExprs;2848 2849 unsigned NumElements = Exp->getNumElements();2850 unsigned UnsignedIntSize =2851 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));2852 Expr *count = IntegerLiteral::Create(*Context,2853 llvm::APInt(UnsignedIntSize, NumElements),2854 Context->UnsignedIntTy, SourceLocation());2855 KeyExprs.push_back(count);2856 ValueExprs.push_back(count);2857 for (unsigned i = 0; i < NumElements; i++) {2858 ObjCDictionaryElement Element = Exp->getKeyValueElement(i);2859 KeyExprs.push_back(Element.Key);2860 ValueExprs.push_back(Element.Value);2861 }2862 2863 // (const id [])objects2864 Expr *NSValueCallExpr =2865 CallExpr::Create(*Context, NSDictDRE, ValueExprs, NSDictFType, VK_LValue,2866 SourceLocation(), FPOptionsOverride());2867 2868 FieldDecl *ARRFD = FieldDecl::Create(*Context, nullptr, SourceLocation(),2869 SourceLocation(),2870 &Context->Idents.get("arr"),2871 Context->getPointerType(Context->VoidPtrTy),2872 nullptr, /*BitWidth=*/nullptr,2873 /*Mutable=*/true, ICIS_NoInit);2874 MemberExpr *DictLiteralValueME =2875 MemberExpr::CreateImplicit(*Context, NSValueCallExpr, false, ARRFD,2876 ARRFD->getType(), VK_LValue, OK_Ordinary);2877 QualType ConstIdT = Context->getObjCIdType().withConst();2878 CStyleCastExpr * DictValueObjects =2879 NoTypeInfoCStyleCastExpr(Context,2880 Context->getPointerType(ConstIdT),2881 CK_BitCast,2882 DictLiteralValueME);2883 // (const id <NSCopying> [])keys2884 Expr *NSKeyCallExpr =2885 CallExpr::Create(*Context, NSDictDRE, KeyExprs, NSDictFType, VK_LValue,2886 SourceLocation(), FPOptionsOverride());2887 2888 MemberExpr *DictLiteralKeyME =2889 MemberExpr::CreateImplicit(*Context, NSKeyCallExpr, false, ARRFD,2890 ARRFD->getType(), VK_LValue, OK_Ordinary);2891 2892 CStyleCastExpr * DictKeyObjects =2893 NoTypeInfoCStyleCastExpr(Context,2894 Context->getPointerType(ConstIdT),2895 CK_BitCast,2896 DictLiteralKeyME);2897 2898 // Synthesize a call to objc_msgSend().2899 SmallVector<Expr*, 32> MsgExprs;2900 SmallVector<Expr*, 4> ClsExprs;2901 QualType expType = Exp->getType();2902 2903 // Create a call to objc_getClass("NSArray"). It will be th 1st argument.2904 ObjCInterfaceDecl *Class =2905 expType->getPointeeType()->castAs<ObjCObjectType>()->getInterface();2906 2907 IdentifierInfo *clsName = Class->getIdentifier();2908 ClsExprs.push_back(getStringLiteral(clsName->getName()));2909 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,2910 StartLoc, EndLoc);2911 MsgExprs.push_back(Cls);2912 2913 // Create a call to sel_registerName("arrayWithObjects:count:").2914 // it will be the 2nd argument.2915 SmallVector<Expr*, 4> SelExprs;2916 ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod();2917 SelExprs.push_back(getStringLiteral(DictMethod->getSelector().getAsString()));2918 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,2919 SelExprs, StartLoc, EndLoc);2920 MsgExprs.push_back(SelExp);2921 2922 // (const id [])objects2923 MsgExprs.push_back(DictValueObjects);2924 2925 // (const id <NSCopying> [])keys2926 MsgExprs.push_back(DictKeyObjects);2927 2928 // (NSUInteger)cnt2929 Expr *cnt = IntegerLiteral::Create(*Context,2930 llvm::APInt(UnsignedIntSize, NumElements),2931 Context->UnsignedIntTy, SourceLocation());2932 MsgExprs.push_back(cnt);2933 2934 SmallVector<QualType, 8> ArgTypes;2935 ArgTypes.push_back(Context->getObjCClassType());2936 ArgTypes.push_back(Context->getObjCSelType());2937 for (const auto *PI : DictMethod->parameters()) {2938 QualType T = PI->getType();2939 if (const PointerType* PT = T->getAs<PointerType>()) {2940 QualType PointeeTy = PT->getPointeeType();2941 convertToUnqualifiedObjCType(PointeeTy);2942 T = Context->getPointerType(PointeeTy);2943 }2944 ArgTypes.push_back(T);2945 }2946 2947 QualType returnType = Exp->getType();2948 // Get the type, we will need to reference it in a couple spots.2949 QualType msgSendType = MsgSendFlavor->getType();2950 2951 // Create a reference to the objc_msgSend() declaration.2952 DeclRefExpr *DRE = new (Context) DeclRefExpr(2953 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());2954 2955 CastExpr *cast = NoTypeInfoCStyleCastExpr(2956 Context, Context->getPointerType(Context->VoidTy), CK_BitCast, DRE);2957 2958 // Now do the "normal" pointer to function cast.2959 QualType castType =2960 getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic());2961 castType = Context->getPointerType(castType);2962 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,2963 cast);2964 2965 // Don't forget the parens to enforce the proper binding.2966 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);2967 2968 const FunctionType *FT = msgSendType->castAs<FunctionType>();2969 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),2970 VK_PRValue, EndLoc, FPOptionsOverride());2971 ReplaceStmt(Exp, CE);2972 return CE;2973}2974 2975// struct __rw_objc_super {2976// struct objc_object *object; struct objc_object *superClass;2977// };2978QualType RewriteModernObjC::getSuperStructType() {2979 if (!SuperStructDecl) {2980 SuperStructDecl = RecordDecl::Create(2981 *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),2982 SourceLocation(), &Context->Idents.get("__rw_objc_super"));2983 QualType FieldTypes[2];2984 2985 // struct objc_object *object;2986 FieldTypes[0] = Context->getObjCIdType();2987 // struct objc_object *superClass;2988 FieldTypes[1] = Context->getObjCIdType();2989 2990 // Create fields2991 for (unsigned i = 0; i < 2; ++i) {2992 SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,2993 SourceLocation(),2994 SourceLocation(), nullptr,2995 FieldTypes[i], nullptr,2996 /*BitWidth=*/nullptr,2997 /*Mutable=*/false,2998 ICIS_NoInit));2999 }3000 3001 SuperStructDecl->completeDefinition();3002 }3003 return Context->getCanonicalTagType(SuperStructDecl);3004}3005 3006QualType RewriteModernObjC::getConstantStringStructType() {3007 if (!ConstantStringDecl) {3008 ConstantStringDecl = RecordDecl::Create(3009 *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),3010 SourceLocation(), &Context->Idents.get("__NSConstantStringImpl"));3011 QualType FieldTypes[4];3012 3013 // struct objc_object *receiver;3014 FieldTypes[0] = Context->getObjCIdType();3015 // int flags;3016 FieldTypes[1] = Context->IntTy;3017 // char *str;3018 FieldTypes[2] = Context->getPointerType(Context->CharTy);3019 // long length;3020 FieldTypes[3] = Context->LongTy;3021 3022 // Create fields3023 for (unsigned i = 0; i < 4; ++i) {3024 ConstantStringDecl->addDecl(FieldDecl::Create(*Context,3025 ConstantStringDecl,3026 SourceLocation(),3027 SourceLocation(), nullptr,3028 FieldTypes[i], nullptr,3029 /*BitWidth=*/nullptr,3030 /*Mutable=*/true,3031 ICIS_NoInit));3032 }3033 3034 ConstantStringDecl->completeDefinition();3035 }3036 return Context->getCanonicalTagType(ConstantStringDecl);3037}3038 3039/// getFunctionSourceLocation - returns start location of a function3040/// definition. Complication arises when function has declared as3041/// extern "C" or extern "C" {...}3042static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R,3043 FunctionDecl *FD) {3044 if (FD->isExternC() && !FD->isMain()) {3045 const DeclContext *DC = FD->getDeclContext();3046 if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))3047 // if it is extern "C" {...}, return function decl's own location.3048 if (!LSD->getRBraceLoc().isValid())3049 return LSD->getExternLoc();3050 }3051 if (FD->getStorageClass() != SC_None)3052 R.RewriteBlockLiteralFunctionDecl(FD);3053 return FD->getTypeSpecStartLoc();3054}3055 3056void RewriteModernObjC::RewriteLineDirective(const Decl *D) {3057 3058 SourceLocation Location = D->getLocation();3059 3060 if (Location.isFileID() && GenerateLineInfo) {3061 std::string LineString("\n#line ");3062 PresumedLoc PLoc = SM->getPresumedLoc(Location);3063 LineString += utostr(PLoc.getLine());3064 LineString += " \"";3065 LineString += Lexer::Stringify(PLoc.getFilename());3066 if (isa<ObjCMethodDecl>(D))3067 LineString += "\"";3068 else LineString += "\"\n";3069 3070 Location = D->getBeginLoc();3071 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {3072 if (FD->isExternC() && !FD->isMain()) {3073 const DeclContext *DC = FD->getDeclContext();3074 if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC))3075 // if it is extern "C" {...}, return function decl's own location.3076 if (!LSD->getRBraceLoc().isValid())3077 Location = LSD->getExternLoc();3078 }3079 }3080 InsertText(Location, LineString);3081 }3082}3083 3084/// SynthMsgSendStretCallExpr - This routine translates message expression3085/// into a call to objc_msgSend_stret() entry point. Tricky part is that3086/// nil check on receiver must be performed before calling objc_msgSend_stret.3087/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...)3088/// msgSendType - function type of objc_msgSend_stret(...)3089/// returnType - Result type of the method being synthesized.3090/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type.3091/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret,3092/// starting with receiver.3093/// Method - Method being rewritten.3094Expr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor,3095 QualType returnType,3096 SmallVectorImpl<QualType> &ArgTypes,3097 SmallVectorImpl<Expr*> &MsgExprs,3098 ObjCMethodDecl *Method) {3099 // Now do the "normal" pointer to function cast.3100 QualType FuncType = getSimpleFunctionType(3101 returnType, ArgTypes, Method ? Method->isVariadic() : false);3102 QualType castType = Context->getPointerType(FuncType);3103 3104 // build type for containing the objc_msgSend_stret object.3105 static unsigned stretCount=0;3106 std::string name = "__Stret"; name += utostr(stretCount);3107 std::string str =3108 "extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n";3109 str += "namespace {\n";3110 str += "struct "; str += name;3111 str += " {\n\t";3112 str += name;3113 str += "(id receiver, SEL sel";3114 for (unsigned i = 2; i < ArgTypes.size(); i++) {3115 std::string ArgName = "arg"; ArgName += utostr(i);3116 ArgTypes[i].getAsStringInternal(ArgName, Context->getPrintingPolicy());3117 str += ", "; str += ArgName;3118 }3119 // could be vararg.3120 for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3121 std::string ArgName = "arg"; ArgName += utostr(i);3122 MsgExprs[i]->getType().getAsStringInternal(ArgName,3123 Context->getPrintingPolicy());3124 str += ", "; str += ArgName;3125 }3126 3127 str += ") {\n";3128 str += "\t unsigned size = sizeof(";3129 str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n";3130 3131 str += "\t if (size == 1 || size == 2 || size == 4 || size == 8)\n";3132 3133 str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());3134 str += ")(void *)objc_msgSend)(receiver, sel";3135 for (unsigned i = 2; i < ArgTypes.size(); i++) {3136 str += ", arg"; str += utostr(i);3137 }3138 // could be vararg.3139 for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3140 str += ", arg"; str += utostr(i);3141 }3142 str+= ");\n";3143 3144 str += "\t else if (receiver == 0)\n";3145 str += "\t memset((void*)&s, 0, sizeof(s));\n";3146 str += "\t else\n";3147 3148 str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy());3149 str += ")(void *)objc_msgSend_stret)(receiver, sel";3150 for (unsigned i = 2; i < ArgTypes.size(); i++) {3151 str += ", arg"; str += utostr(i);3152 }3153 // could be vararg.3154 for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) {3155 str += ", arg"; str += utostr(i);3156 }3157 str += ");\n";3158 3159 str += "\t}\n";3160 str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy());3161 str += " s;\n";3162 str += "};\n};\n\n";3163 SourceLocation FunLocStart;3164 if (CurFunctionDef)3165 FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);3166 else {3167 assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null");3168 FunLocStart = CurMethodDef->getBeginLoc();3169 }3170 3171 InsertText(FunLocStart, str);3172 ++stretCount;3173 3174 // AST for __Stretn(receiver, args).s;3175 IdentifierInfo *ID = &Context->Idents.get(name);3176 FunctionDecl *FD =3177 FunctionDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(),3178 ID, FuncType, nullptr, SC_Extern, false, false);3179 DeclRefExpr *DRE = new (Context)3180 DeclRefExpr(*Context, FD, false, castType, VK_PRValue, SourceLocation());3181 CallExpr *STCE =3182 CallExpr::Create(*Context, DRE, MsgExprs, castType, VK_LValue,3183 SourceLocation(), FPOptionsOverride());3184 3185 FieldDecl *FieldD = FieldDecl::Create(*Context, nullptr, SourceLocation(),3186 SourceLocation(),3187 &Context->Idents.get("s"),3188 returnType, nullptr,3189 /*BitWidth=*/nullptr,3190 /*Mutable=*/true, ICIS_NoInit);3191 MemberExpr *ME = MemberExpr::CreateImplicit(3192 *Context, STCE, false, FieldD, FieldD->getType(), VK_LValue, OK_Ordinary);3193 3194 return ME;3195}3196 3197Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp,3198 SourceLocation StartLoc,3199 SourceLocation EndLoc) {3200 if (!SelGetUidFunctionDecl)3201 SynthSelGetUidFunctionDecl();3202 if (!MsgSendFunctionDecl)3203 SynthMsgSendFunctionDecl();3204 if (!MsgSendSuperFunctionDecl)3205 SynthMsgSendSuperFunctionDecl();3206 if (!MsgSendStretFunctionDecl)3207 SynthMsgSendStretFunctionDecl();3208 if (!MsgSendSuperStretFunctionDecl)3209 SynthMsgSendSuperStretFunctionDecl();3210 if (!MsgSendFpretFunctionDecl)3211 SynthMsgSendFpretFunctionDecl();3212 if (!GetClassFunctionDecl)3213 SynthGetClassFunctionDecl();3214 if (!GetSuperClassFunctionDecl)3215 SynthGetSuperClassFunctionDecl();3216 if (!GetMetaClassFunctionDecl)3217 SynthGetMetaClassFunctionDecl();3218 3219 // default to objc_msgSend().3220 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;3221 // May need to use objc_msgSend_stret() as well.3222 FunctionDecl *MsgSendStretFlavor = nullptr;3223 if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {3224 QualType resultType = mDecl->getReturnType();3225 if (resultType->isRecordType())3226 MsgSendStretFlavor = MsgSendStretFunctionDecl;3227 else if (resultType->isRealFloatingType())3228 MsgSendFlavor = MsgSendFpretFunctionDecl;3229 }3230 3231 // Synthesize a call to objc_msgSend().3232 SmallVector<Expr*, 8> MsgExprs;3233 switch (Exp->getReceiverKind()) {3234 case ObjCMessageExpr::SuperClass: {3235 MsgSendFlavor = MsgSendSuperFunctionDecl;3236 if (MsgSendStretFlavor)3237 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;3238 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");3239 3240 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();3241 3242 SmallVector<Expr*, 4> InitExprs;3243 3244 // set the receiver to self, the first argument to all methods.3245 InitExprs.push_back(NoTypeInfoCStyleCastExpr(3246 Context, Context->getObjCIdType(), CK_BitCast,3247 new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,3248 Context->getObjCIdType(), VK_PRValue,3249 SourceLocation()))); // set the 'receiver'.3250 3251 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3252 SmallVector<Expr*, 8> ClsExprs;3253 ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));3254 // (Class)objc_getClass("CurrentClass")3255 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,3256 ClsExprs, StartLoc, EndLoc);3257 ClsExprs.clear();3258 ClsExprs.push_back(Cls);3259 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,3260 StartLoc, EndLoc);3261 3262 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3263 // To turn off a warning, type-cast to 'id'3264 InitExprs.push_back( // set 'super class', using class_getSuperclass().3265 NoTypeInfoCStyleCastExpr(Context,3266 Context->getObjCIdType(),3267 CK_BitCast, Cls));3268 // struct __rw_objc_super3269 QualType superType = getSuperStructType();3270 Expr *SuperRep;3271 3272 if (LangOpts.MicrosoftExt) {3273 SynthSuperConstructorFunctionDecl();3274 // Simulate a constructor call...3275 DeclRefExpr *DRE = new (Context)3276 DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,3277 VK_LValue, SourceLocation());3278 SuperRep =3279 CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,3280 SourceLocation(), FPOptionsOverride());3281 // The code for super is a little tricky to prevent collision with3282 // the structure definition in the header. The rewriter has it's own3283 // internal definition (__rw_objc_super) that is uses. This is why3284 // we need the cast below. For example:3285 // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))3286 //3287 SuperRep = UnaryOperator::Create(3288 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3289 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3290 SourceLocation(), false, FPOptionsOverride());3291 SuperRep = NoTypeInfoCStyleCastExpr(Context,3292 Context->getPointerType(superType),3293 CK_BitCast, SuperRep);3294 } else {3295 // (struct __rw_objc_super) { <exprs from above> }3296 InitListExpr *ILE =3297 new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,3298 SourceLocation());3299 TypeSourceInfo *superTInfo3300 = Context->getTrivialTypeSourceInfo(superType);3301 SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,3302 superType, VK_LValue,3303 ILE, false);3304 // struct __rw_objc_super *3305 SuperRep = UnaryOperator::Create(3306 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3307 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3308 SourceLocation(), false, FPOptionsOverride());3309 }3310 MsgExprs.push_back(SuperRep);3311 break;3312 }3313 3314 case ObjCMessageExpr::Class: {3315 SmallVector<Expr*, 8> ClsExprs;3316 ObjCInterfaceDecl *Class3317 = Exp->getClassReceiver()->castAs<ObjCObjectType>()->getInterface();3318 IdentifierInfo *clsName = Class->getIdentifier();3319 ClsExprs.push_back(getStringLiteral(clsName->getName()));3320 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,3321 StartLoc, EndLoc);3322 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context,3323 Context->getObjCIdType(),3324 CK_BitCast, Cls);3325 MsgExprs.push_back(ArgExpr);3326 break;3327 }3328 3329 case ObjCMessageExpr::SuperInstance:{3330 MsgSendFlavor = MsgSendSuperFunctionDecl;3331 if (MsgSendStretFlavor)3332 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;3333 assert(MsgSendFlavor && "MsgSendFlavor is NULL!");3334 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface();3335 SmallVector<Expr*, 4> InitExprs;3336 3337 InitExprs.push_back(NoTypeInfoCStyleCastExpr(3338 Context, Context->getObjCIdType(), CK_BitCast,3339 new (Context) DeclRefExpr(*Context, CurMethodDef->getSelfDecl(), false,3340 Context->getObjCIdType(), VK_PRValue,3341 SourceLocation()))); // set the 'receiver'.3342 3343 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3344 SmallVector<Expr*, 8> ClsExprs;3345 ClsExprs.push_back(getStringLiteral(ClassDecl->getIdentifier()->getName()));3346 // (Class)objc_getClass("CurrentClass")3347 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, ClsExprs,3348 StartLoc, EndLoc);3349 ClsExprs.clear();3350 ClsExprs.push_back(Cls);3351 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, ClsExprs,3352 StartLoc, EndLoc);3353 3354 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass"))3355 // To turn off a warning, type-cast to 'id'3356 InitExprs.push_back(3357 // set 'super class', using class_getSuperclass().3358 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3359 CK_BitCast, Cls));3360 // struct __rw_objc_super3361 QualType superType = getSuperStructType();3362 Expr *SuperRep;3363 3364 if (LangOpts.MicrosoftExt) {3365 SynthSuperConstructorFunctionDecl();3366 // Simulate a constructor call...3367 DeclRefExpr *DRE = new (Context)3368 DeclRefExpr(*Context, SuperConstructorFunctionDecl, false, superType,3369 VK_LValue, SourceLocation());3370 SuperRep =3371 CallExpr::Create(*Context, DRE, InitExprs, superType, VK_LValue,3372 SourceLocation(), FPOptionsOverride());3373 // The code for super is a little tricky to prevent collision with3374 // the structure definition in the header. The rewriter has it's own3375 // internal definition (__rw_objc_super) that is uses. This is why3376 // we need the cast below. For example:3377 // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))3378 //3379 SuperRep = UnaryOperator::Create(3380 const_cast<ASTContext &>(*Context), SuperRep, UO_AddrOf,3381 Context->getPointerType(SuperRep->getType()), VK_PRValue, OK_Ordinary,3382 SourceLocation(), false, FPOptionsOverride());3383 SuperRep = NoTypeInfoCStyleCastExpr(Context,3384 Context->getPointerType(superType),3385 CK_BitCast, SuperRep);3386 } else {3387 // (struct __rw_objc_super) { <exprs from above> }3388 InitListExpr *ILE =3389 new (Context) InitListExpr(*Context, SourceLocation(), InitExprs,3390 SourceLocation());3391 TypeSourceInfo *superTInfo3392 = Context->getTrivialTypeSourceInfo(superType);3393 SuperRep = new (Context) CompoundLiteralExpr(3394 SourceLocation(), superTInfo, superType, VK_PRValue, ILE, false);3395 }3396 MsgExprs.push_back(SuperRep);3397 break;3398 }3399 3400 case ObjCMessageExpr::Instance: {3401 // Remove all type-casts because it may contain objc-style types; e.g.3402 // Foo<Proto> *.3403 Expr *recExpr = Exp->getInstanceReceiver();3404 while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))3405 recExpr = CE->getSubExpr();3406 CastKind CK = recExpr->getType()->isObjCObjectPointerType()3407 ? CK_BitCast : recExpr->getType()->isBlockPointerType()3408 ? CK_BlockPointerToObjCPointerCast3409 : CK_CPointerToObjCPointerCast;3410 3411 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3412 CK, recExpr);3413 MsgExprs.push_back(recExpr);3414 break;3415 }3416 }3417 3418 // Create a call to sel_registerName("selName"), it will be the 2nd argument.3419 SmallVector<Expr*, 8> SelExprs;3420 SelExprs.push_back(getStringLiteral(Exp->getSelector().getAsString()));3421 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,3422 SelExprs, StartLoc, EndLoc);3423 MsgExprs.push_back(SelExp);3424 3425 // Now push any user supplied arguments.3426 for (unsigned i = 0; i < Exp->getNumArgs(); i++) {3427 Expr *userExpr = Exp->getArg(i);3428 // Make all implicit casts explicit...ICE comes in handy:-)3429 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {3430 // Reuse the ICE type, it is exactly what the doctor ordered.3431 QualType type = ICE->getType();3432 if (needToScanForQualifiers(type))3433 type = Context->getObjCIdType();3434 // Make sure we convert "type (^)(...)" to "type (*)(...)".3435 (void)convertBlockPointerToFunctionPointer(type);3436 const Expr *SubExpr = ICE->IgnoreParenImpCasts();3437 CastKind CK;3438 if (SubExpr->getType()->isIntegralType(*Context) &&3439 type->isBooleanType()) {3440 CK = CK_IntegralToBoolean;3441 } else if (type->isObjCObjectPointerType()) {3442 if (SubExpr->getType()->isBlockPointerType()) {3443 CK = CK_BlockPointerToObjCPointerCast;3444 } else if (SubExpr->getType()->isPointerType()) {3445 CK = CK_CPointerToObjCPointerCast;3446 } else {3447 CK = CK_BitCast;3448 }3449 } else {3450 CK = CK_BitCast;3451 }3452 3453 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr);3454 }3455 // Make id<P...> cast into an 'id' cast.3456 else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {3457 if (CE->getType()->isObjCQualifiedIdType()) {3458 while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))3459 userExpr = CE->getSubExpr();3460 CastKind CK;3461 if (userExpr->getType()->isIntegralType(*Context)) {3462 CK = CK_IntegralToPointer;3463 } else if (userExpr->getType()->isBlockPointerType()) {3464 CK = CK_BlockPointerToObjCPointerCast;3465 } else if (userExpr->getType()->isPointerType()) {3466 CK = CK_CPointerToObjCPointerCast;3467 } else {3468 CK = CK_BitCast;3469 }3470 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),3471 CK, userExpr);3472 }3473 }3474 MsgExprs.push_back(userExpr);3475 // We've transferred the ownership to MsgExprs. For now, we *don't* null3476 // out the argument in the original expression (since we aren't deleting3477 // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info.3478 //Exp->setArg(i, 0);3479 }3480 // Generate the funky cast.3481 CastExpr *cast;3482 SmallVector<QualType, 8> ArgTypes;3483 QualType returnType;3484 3485 // Push 'id' and 'SEL', the 2 implicit arguments.3486 if (MsgSendFlavor == MsgSendSuperFunctionDecl)3487 ArgTypes.push_back(Context->getPointerType(getSuperStructType()));3488 else3489 ArgTypes.push_back(Context->getObjCIdType());3490 ArgTypes.push_back(Context->getObjCSelType());3491 if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {3492 // Push any user argument types.3493 for (const auto *PI : OMD->parameters()) {3494 QualType t = PI->getType()->isObjCQualifiedIdType()3495 ? Context->getObjCIdType()3496 : PI->getType();3497 // Make sure we convert "t (^)(...)" to "t (*)(...)".3498 (void)convertBlockPointerToFunctionPointer(t);3499 ArgTypes.push_back(t);3500 }3501 returnType = Exp->getType();3502 convertToUnqualifiedObjCType(returnType);3503 (void)convertBlockPointerToFunctionPointer(returnType);3504 } else {3505 returnType = Context->getObjCIdType();3506 }3507 // Get the type, we will need to reference it in a couple spots.3508 QualType msgSendType = MsgSendFlavor->getType();3509 3510 // Create a reference to the objc_msgSend() declaration.3511 DeclRefExpr *DRE = new (Context) DeclRefExpr(3512 *Context, MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation());3513 3514 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).3515 // If we don't do this cast, we get the following bizarre warning/note:3516 // xx.m:13: warning: function called through a non-compatible type3517 // xx.m:13: note: if this code is reached, the program will abort3518 cast = NoTypeInfoCStyleCastExpr(Context,3519 Context->getPointerType(Context->VoidTy),3520 CK_BitCast, DRE);3521 3522 // Now do the "normal" pointer to function cast.3523 // If we don't have a method decl, force a variadic cast.3524 const ObjCMethodDecl *MD = Exp->getMethodDecl();3525 QualType castType =3526 getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true);3527 castType = Context->getPointerType(castType);3528 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast,3529 cast);3530 3531 // Don't forget the parens to enforce the proper binding.3532 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast);3533 3534 const FunctionType *FT = msgSendType->castAs<FunctionType>();3535 CallExpr *CE = CallExpr::Create(*Context, PE, MsgExprs, FT->getReturnType(),3536 VK_PRValue, EndLoc, FPOptionsOverride());3537 Stmt *ReplacingStmt = CE;3538 if (MsgSendStretFlavor) {3539 // We have the method which returns a struct/union. Must also generate3540 // call to objc_msgSend_stret and hang both varieties on a conditional3541 // expression which dictate which one to envoke depending on size of3542 // method's return type.3543 3544 Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor,3545 returnType,3546 ArgTypes, MsgExprs,3547 Exp->getMethodDecl());3548 ReplacingStmt = STCE;3549 }3550 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3551 return ReplacingStmt;3552}3553 3554Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {3555 Stmt *ReplacingStmt =3556 SynthMessageExpr(Exp, Exp->getBeginLoc(), Exp->getEndLoc());3557 3558 // Now do the actual rewrite.3559 ReplaceStmt(Exp, ReplacingStmt);3560 3561 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3562 return ReplacingStmt;3563}3564 3565// typedef struct objc_object Protocol;3566QualType RewriteModernObjC::getProtocolType() {3567 if (!ProtocolTypeDecl) {3568 TypeSourceInfo *TInfo3569 = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());3570 ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,3571 SourceLocation(), SourceLocation(),3572 &Context->Idents.get("Protocol"),3573 TInfo);3574 }3575 return Context->getTypeDeclType(ProtocolTypeDecl);3576}3577 3578/// RewriteObjCProtocolExpr - Rewrite a protocol expression into3579/// a synthesized/forward data reference (to the protocol's metadata).3580/// The forward references (and metadata) are generated in3581/// RewriteModernObjC::HandleTranslationUnit().3582Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {3583 std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" +3584 Exp->getProtocol()->getNameAsString();3585 IdentifierInfo *ID = &Context->Idents.get(Name);3586 VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),3587 SourceLocation(), ID, getProtocolType(),3588 nullptr, SC_Extern);3589 DeclRefExpr *DRE = new (Context) DeclRefExpr(3590 *Context, VD, false, getProtocolType(), VK_LValue, SourceLocation());3591 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(3592 Context, Context->getPointerType(DRE->getType()), CK_BitCast, DRE);3593 ReplaceStmt(Exp, castExpr);3594 ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl());3595 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info.3596 return castExpr;3597}3598 3599/// IsTagDefinedInsideClass - This routine checks that a named tagged type3600/// is defined inside an objective-c class. If so, it returns true.3601bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl,3602 TagDecl *Tag,3603 bool &IsNamedDefinition) {3604 if (!IDecl)3605 return false;3606 SourceLocation TagLocation;3607 if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) {3608 RD = RD->getDefinition();3609 if (!RD || !RD->getDeclName().getAsIdentifierInfo())3610 return false;3611 IsNamedDefinition = true;3612 TagLocation = RD->getLocation();3613 return Context->getSourceManager().isBeforeInTranslationUnit(3614 IDecl->getLocation(), TagLocation);3615 }3616 if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) {3617 if (!ED || !ED->getDeclName().getAsIdentifierInfo())3618 return false;3619 IsNamedDefinition = true;3620 TagLocation = ED->getLocation();3621 return Context->getSourceManager().isBeforeInTranslationUnit(3622 IDecl->getLocation(), TagLocation);3623 }3624 return false;3625}3626 3627/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer.3628/// It handles elaborated types, as well as enum types in the process.3629bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type,3630 std::string &Result) {3631 if (Type->getAs<TypedefType>()) {3632 Result += "\t";3633 return false;3634 }3635 3636 if (Type->isArrayType()) {3637 QualType ElemTy = Context->getBaseElementType(Type);3638 return RewriteObjCFieldDeclType(ElemTy, Result);3639 }3640 else if (Type->isRecordType()) {3641 auto *RD = Type->castAsRecordDecl();3642 if (RD->isCompleteDefinition()) {3643 if (RD->isStruct())3644 Result += "\n\tstruct ";3645 else if (RD->isUnion())3646 Result += "\n\tunion ";3647 else3648 assert(false && "class not allowed as an ivar type");3649 3650 Result += RD->getName();3651 if (GlobalDefinedTags.count(RD)) {3652 // struct/union is defined globally, use it.3653 Result += " ";3654 return true;3655 }3656 Result += " {\n";3657 for (auto *FD : RD->fields())3658 RewriteObjCFieldDecl(FD, Result);3659 Result += "\t} ";3660 return true;3661 }3662 } else if (auto *ED = Type->getAsEnumDecl();3663 ED && ED->isCompleteDefinition()) {3664 Result += "\n\tenum ";3665 Result += ED->getName();3666 if (GlobalDefinedTags.count(ED)) {3667 // Enum is globall defined, use it.3668 Result += " ";3669 return true;3670 }3671 3672 Result += " {\n";3673 for (const auto *EC : ED->enumerators()) {3674 Result += "\t";3675 Result += EC->getName();3676 Result += " = ";3677 Result += toString(EC->getInitVal(), 10);3678 Result += ",\n";3679 }3680 Result += "\t} ";3681 return true;3682 }3683 3684 Result += "\t";3685 convertObjCTypeToCStyleType(Type);3686 return false;3687}3688 3689 3690/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer.3691/// It handles elaborated types, as well as enum types in the process.3692void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl,3693 std::string &Result) {3694 QualType Type = fieldDecl->getType();3695 std::string Name = fieldDecl->getNameAsString();3696 3697 bool EleboratedType = RewriteObjCFieldDeclType(Type, Result);3698 if (!EleboratedType)3699 Type.getAsStringInternal(Name, Context->getPrintingPolicy());3700 Result += Name;3701 if (fieldDecl->isBitField()) {3702 Result += " : ";3703 Result += utostr(fieldDecl->getBitWidthValue());3704 }3705 else if (EleboratedType && Type->isArrayType()) {3706 const ArrayType *AT = Context->getAsArrayType(Type);3707 do {3708 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) {3709 Result += "[";3710 llvm::APInt Dim = CAT->getSize();3711 Result += utostr(Dim.getZExtValue());3712 Result += "]";3713 }3714 AT = Context->getAsArrayType(AT->getElementType());3715 } while (AT);3716 }3717 3718 Result += ";\n";3719}3720 3721/// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined3722/// named aggregate types into the input buffer.3723void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl,3724 std::string &Result) {3725 QualType Type = fieldDecl->getType();3726 if (Type->getAs<TypedefType>())3727 return;3728 if (Type->isArrayType())3729 Type = Context->getBaseElementType(Type);3730 3731 auto *IDecl = dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext());3732 3733 if (auto *TD = Type->getAsTagDecl()) {3734 if (GlobalDefinedTags.count(TD))3735 return;3736 3737 bool IsNamedDefinition = false;3738 if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) {3739 RewriteObjCFieldDeclType(Type, Result);3740 Result += ";";3741 }3742 if (IsNamedDefinition)3743 GlobalDefinedTags.insert(TD);3744 }3745}3746 3747unsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) {3748 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3749 if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) {3750 return IvarGroupNumber[IV];3751 }3752 unsigned GroupNo = 0;3753 SmallVector<const ObjCIvarDecl *, 8> IVars;3754 for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3755 IVD; IVD = IVD->getNextIvar())3756 IVars.push_back(IVD);3757 3758 for (unsigned i = 0, e = IVars.size(); i < e; i++)3759 if (IVars[i]->isBitField()) {3760 IvarGroupNumber[IVars[i++]] = ++GroupNo;3761 while (i < e && IVars[i]->isBitField())3762 IvarGroupNumber[IVars[i++]] = GroupNo;3763 if (i < e)3764 --i;3765 }3766 3767 ObjCInterefaceHasBitfieldGroups.insert(CDecl);3768 return IvarGroupNumber[IV];3769}3770 3771QualType RewriteModernObjC::SynthesizeBitfieldGroupStructType(3772 ObjCIvarDecl *IV,3773 SmallVectorImpl<ObjCIvarDecl *> &IVars) {3774 std::string StructTagName;3775 ObjCIvarBitfieldGroupType(IV, StructTagName);3776 RecordDecl *RD = RecordDecl::Create(3777 *Context, TagTypeKind::Struct, Context->getTranslationUnitDecl(),3778 SourceLocation(), SourceLocation(), &Context->Idents.get(StructTagName));3779 for (unsigned i=0, e = IVars.size(); i < e; i++) {3780 ObjCIvarDecl *Ivar = IVars[i];3781 RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(),3782 &Context->Idents.get(Ivar->getName()),3783 Ivar->getType(),3784 nullptr, /*Expr *BW */Ivar->getBitWidth(),3785 false, ICIS_NoInit));3786 }3787 RD->completeDefinition();3788 return Context->getCanonicalTagType(RD);3789}3790 3791QualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) {3792 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3793 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3794 std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo);3795 if (auto It = GroupRecordType.find(tuple); It != GroupRecordType.end())3796 return It->second;3797 3798 SmallVector<ObjCIvarDecl *, 8> IVars;3799 for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3800 IVD; IVD = IVD->getNextIvar()) {3801 if (IVD->isBitField())3802 IVars.push_back(const_cast<ObjCIvarDecl *>(IVD));3803 else {3804 if (!IVars.empty()) {3805 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);3806 // Generate the struct type for this group of bitfield ivars.3807 GroupRecordType[std::make_pair(CDecl, GroupNo)] =3808 SynthesizeBitfieldGroupStructType(IVars[0], IVars);3809 IVars.clear();3810 }3811 }3812 }3813 if (!IVars.empty()) {3814 // Do the last one.3815 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]);3816 GroupRecordType[std::make_pair(CDecl, GroupNo)] =3817 SynthesizeBitfieldGroupStructType(IVars[0], IVars);3818 }3819 QualType RetQT = GroupRecordType[tuple];3820 assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL");3821 3822 return RetQT;3823}3824 3825/// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group.3826/// Name would be: classname__GRBF_n where n is the group number for this ivar.3827void RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV,3828 std::string &Result) {3829 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3830 Result += CDecl->getName();3831 Result += "__GRBF_";3832 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3833 Result += utostr(GroupNo);3834}3835 3836/// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group.3837/// Name of the struct would be: classname__T_n where n is the group number for3838/// this ivar.3839void RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV,3840 std::string &Result) {3841 const ObjCInterfaceDecl *CDecl = IV->getContainingInterface();3842 Result += CDecl->getName();3843 Result += "__T_";3844 unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV);3845 Result += utostr(GroupNo);3846}3847 3848/// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset.3849/// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for3850/// this ivar.3851void RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV,3852 std::string &Result) {3853 Result += "OBJC_IVAR_$_";3854 ObjCIvarBitfieldGroupDecl(IV, Result);3855}3856 3857#define SKIP_BITFIELDS(IX, ENDIX, VEC) { \3858 while ((IX < ENDIX) && VEC[IX]->isBitField()) \3859 ++IX; \3860 if (IX < ENDIX) \3861 --IX; \3862}3863 3864/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to3865/// an objective-c class with ivars.3866void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl,3867 std::string &Result) {3868 assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");3869 assert(CDecl->getName() != "" &&3870 "Name missing in SynthesizeObjCInternalStruct");3871 ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();3872 SmallVector<ObjCIvarDecl *, 8> IVars;3873 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();3874 IVD; IVD = IVD->getNextIvar())3875 IVars.push_back(IVD);3876 3877 SourceLocation LocStart = CDecl->getBeginLoc();3878 SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc();3879 3880 const char *startBuf = SM->getCharacterData(LocStart);3881 const char *endBuf = SM->getCharacterData(LocEnd);3882 3883 // If no ivars and no root or if its root, directly or indirectly,3884 // have no ivars (thus not synthesized) then no need to synthesize this class.3885 if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) &&3886 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {3887 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3888 ReplaceText(LocStart, endBuf-startBuf, Result);3889 return;3890 }3891 3892 // Insert named struct/union definitions inside class to3893 // outer scope. This follows semantics of locally defined3894 // struct/unions in objective-c classes.3895 for (unsigned i = 0, e = IVars.size(); i < e; i++)3896 RewriteLocallyDefinedNamedAggregates(IVars[i], Result);3897 3898 // Insert named structs which are syntheized to group ivar bitfields3899 // to outer scope as well.3900 for (unsigned i = 0, e = IVars.size(); i < e; i++)3901 if (IVars[i]->isBitField()) {3902 ObjCIvarDecl *IV = IVars[i];3903 QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV);3904 RewriteObjCFieldDeclType(QT, Result);3905 Result += ";";3906 // skip over ivar bitfields in this group.3907 SKIP_BITFIELDS(i , e, IVars);3908 }3909 3910 Result += "\nstruct ";3911 Result += CDecl->getNameAsString();3912 Result += "_IMPL {\n";3913 3914 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {3915 Result += "\tstruct "; Result += RCDecl->getNameAsString();3916 Result += "_IMPL "; Result += RCDecl->getNameAsString();3917 Result += "_IVARS;\n";3918 }3919 3920 for (unsigned i = 0, e = IVars.size(); i < e; i++) {3921 if (IVars[i]->isBitField()) {3922 ObjCIvarDecl *IV = IVars[i];3923 Result += "\tstruct ";3924 ObjCIvarBitfieldGroupType(IV, Result); Result += " ";3925 ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n";3926 // skip over ivar bitfields in this group.3927 SKIP_BITFIELDS(i , e, IVars);3928 }3929 else3930 RewriteObjCFieldDecl(IVars[i], Result);3931 }3932 3933 Result += "};\n";3934 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);3935 ReplaceText(LocStart, endBuf-startBuf, Result);3936 // Mark this struct as having been generated.3937 if (!ObjCSynthesizedStructs.insert(CDecl).second)3938 llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct");3939}3940 3941/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which3942/// have been referenced in an ivar access expression.3943void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl,3944 std::string &Result) {3945 // write out ivar offset symbols which have been referenced in an ivar3946 // access expression.3947 llvm::SmallSetVector<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl];3948 3949 if (Ivars.empty())3950 return;3951 3952 llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput;3953 for (ObjCIvarDecl *IvarDecl : Ivars) {3954 const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface();3955 unsigned GroupNo = 0;3956 if (IvarDecl->isBitField()) {3957 GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl);3958 if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo)))3959 continue;3960 }3961 Result += "\n";3962 if (LangOpts.MicrosoftExt)3963 Result += "__declspec(allocate(\".objc_ivar$B\")) ";3964 Result += "extern \"C\" ";3965 if (LangOpts.MicrosoftExt &&3966 IvarDecl->getAccessControl() != ObjCIvarDecl::Private &&3967 IvarDecl->getAccessControl() != ObjCIvarDecl::Package)3968 Result += "__declspec(dllimport) ";3969 3970 Result += "unsigned long ";3971 if (IvarDecl->isBitField()) {3972 ObjCIvarBitfieldGroupOffset(IvarDecl, Result);3973 GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo));3974 }3975 else3976 WriteInternalIvarName(CDecl, IvarDecl, Result);3977 Result += ";";3978 }3979}3980 3981//===----------------------------------------------------------------------===//3982// Meta Data Emission3983//===----------------------------------------------------------------------===//3984 3985/// RewriteImplementations - This routine rewrites all method implementations3986/// and emits meta-data.3987 3988void RewriteModernObjC::RewriteImplementations() {3989 int ClsDefCount = ClassImplementation.size();3990 int CatDefCount = CategoryImplementation.size();3991 3992 // Rewrite implemented methods3993 for (int i = 0; i < ClsDefCount; i++) {3994 ObjCImplementationDecl *OIMP = ClassImplementation[i];3995 ObjCInterfaceDecl *CDecl = OIMP->getClassInterface();3996 if (CDecl->isImplicitInterfaceDecl())3997 assert(false &&3998 "Legacy implicit interface rewriting not supported in moder abi");3999 RewriteImplementationDecl(OIMP);4000 }4001 4002 for (int i = 0; i < CatDefCount; i++) {4003 ObjCCategoryImplDecl *CIMP = CategoryImplementation[i];4004 ObjCInterfaceDecl *CDecl = CIMP->getClassInterface();4005 if (CDecl->isImplicitInterfaceDecl())4006 assert(false &&4007 "Legacy implicit interface rewriting not supported in moder abi");4008 RewriteImplementationDecl(CIMP);4009 }4010}4011 4012void RewriteModernObjC::RewriteByRefString(std::string &ResultStr,4013 const std::string &Name,4014 ValueDecl *VD, bool def) {4015 assert(BlockByRefDeclNo.count(VD) &&4016 "RewriteByRefString: ByRef decl missing");4017 if (def)4018 ResultStr += "struct ";4019 ResultStr += "__Block_byref_" + Name +4020 "_" + utostr(BlockByRefDeclNo[VD]) ;4021}4022 4023static bool HasLocalVariableExternalStorage(ValueDecl *VD) {4024 if (VarDecl *Var = dyn_cast<VarDecl>(VD))4025 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());4026 return false;4027}4028 4029std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,4030 StringRef funcName,4031 const std::string &Tag) {4032 const FunctionType *AFT = CE->getFunctionType();4033 QualType RT = AFT->getReturnType();4034 std::string StructRef = "struct " + Tag;4035 SourceLocation BlockLoc = CE->getExprLoc();4036 std::string S;4037 ConvertSourceLocationToLineDirective(BlockLoc, S);4038 4039 S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" +4040 funcName.str() + "_block_func_" + utostr(i);4041 4042 BlockDecl *BD = CE->getBlockDecl();4043 4044 if (isa<FunctionNoProtoType>(AFT)) {4045 // No user-supplied arguments. Still need to pass in a pointer to the4046 // block (to reference imported block decl refs).4047 S += "(" + StructRef + " *__cself)";4048 } else if (BD->param_empty()) {4049 S += "(" + StructRef + " *__cself)";4050 } else {4051 const FunctionProtoType *FT = cast<FunctionProtoType>(AFT);4052 assert(FT && "SynthesizeBlockFunc: No function proto");4053 S += '(';4054 // first add the implicit argument.4055 S += StructRef + " *__cself, ";4056 std::string ParamStr;4057 for (BlockDecl::param_iterator AI = BD->param_begin(),4058 E = BD->param_end(); AI != E; ++AI) {4059 if (AI != BD->param_begin()) S += ", ";4060 ParamStr = (*AI)->getNameAsString();4061 QualType QT = (*AI)->getType();4062 (void)convertBlockPointerToFunctionPointer(QT);4063 QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy());4064 S += ParamStr;4065 }4066 if (FT->isVariadic()) {4067 if (!BD->param_empty()) S += ", ";4068 S += "...";4069 }4070 S += ')';4071 }4072 S += " {\n";4073 4074 // Create local declarations to avoid rewriting all closure decl ref exprs.4075 // First, emit a declaration for all "by ref" decls.4076 for (ValueDecl *VD : BlockByRefDecls) {4077 S += " ";4078 std::string Name = VD->getNameAsString();4079 std::string TypeString;4080 RewriteByRefString(TypeString, Name, VD);4081 TypeString += " *";4082 Name = TypeString + Name;4083 S += Name + " = __cself->" + VD->getNameAsString() + "; // bound by ref\n";4084 }4085 // Next, emit a declaration for all "by copy" declarations.4086 for (ValueDecl *VD : BlockByCopyDecls) {4087 S += " ";4088 // Handle nested closure invocation. For example:4089 //4090 // void (^myImportedClosure)(void);4091 // myImportedClosure = ^(void) { setGlobalInt(x + y); };4092 //4093 // void (^anotherClosure)(void);4094 // anotherClosure = ^(void) {4095 // myImportedClosure(); // import and invoke the closure4096 // };4097 //4098 if (isTopLevelBlockPointerType(VD->getType())) {4099 RewriteBlockPointerTypeVariable(S, VD);4100 S += " = (";4101 RewriteBlockPointerType(S, VD->getType());4102 S += ")";4103 S += "__cself->" + VD->getNameAsString() + "; // bound by copy\n";4104 } else {4105 std::string Name = VD->getNameAsString();4106 QualType QT = VD->getType();4107 if (HasLocalVariableExternalStorage(VD))4108 QT = Context->getPointerType(QT);4109 QT.getAsStringInternal(Name, Context->getPrintingPolicy());4110 S += Name + " = __cself->" + VD->getNameAsString() +4111 "; // bound by copy\n";4112 }4113 }4114 std::string RewrittenStr = RewrittenBlockExprs[CE];4115 const char *cstr = RewrittenStr.c_str();4116 while (*cstr++ != '{') ;4117 S += cstr;4118 S += "\n";4119 return S;4120}4121 4122std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(4123 BlockExpr *CE, int i, StringRef funcName, const std::string &Tag) {4124 std::string StructRef = "struct " + Tag;4125 std::string S = "static void __";4126 4127 S += funcName;4128 S += "_block_copy_" + utostr(i);4129 S += "(" + StructRef;4130 S += "*dst, " + StructRef;4131 S += "*src) {";4132 for (ValueDecl *VD : ImportedBlockDecls) {4133 S += "_Block_object_assign((void*)&dst->";4134 S += VD->getNameAsString();4135 S += ", (void*)src->";4136 S += VD->getNameAsString();4137 if (BlockByRefDecls.count(VD))4138 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";4139 else if (VD->getType()->isBlockPointerType())4140 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";4141 else4142 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";4143 }4144 S += "}\n";4145 4146 S += "\nstatic void __";4147 S += funcName;4148 S += "_block_dispose_" + utostr(i);4149 S += "(" + StructRef;4150 S += "*src) {";4151 for (ValueDecl *VD : ImportedBlockDecls) {4152 S += "_Block_object_dispose((void*)src->";4153 S += VD->getNameAsString();4154 if (BlockByRefDecls.count(VD))4155 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);";4156 else if (VD->getType()->isBlockPointerType())4157 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);";4158 else4159 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);";4160 }4161 S += "}\n";4162 return S;4163}4164 4165std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE,4166 const std::string &Tag,4167 const std::string &Desc) {4168 std::string S = "\nstruct " + Tag;4169 std::string Constructor = " " + Tag;4170 4171 S += " {\n struct __block_impl impl;\n";4172 S += " struct " + Desc;4173 S += "* Desc;\n";4174 4175 Constructor += "(void *fp, "; // Invoke function pointer.4176 Constructor += "struct " + Desc; // Descriptor pointer.4177 Constructor += " *desc";4178 4179 if (BlockDeclRefs.size()) {4180 // Output all "by copy" declarations.4181 for (ValueDecl *VD : BlockByCopyDecls) {4182 S += " ";4183 std::string FieldName = VD->getNameAsString();4184 std::string ArgName = "_" + FieldName;4185 // Handle nested closure invocation. For example:4186 //4187 // void (^myImportedBlock)(void);4188 // myImportedBlock = ^(void) { setGlobalInt(x + y); };4189 //4190 // void (^anotherBlock)(void);4191 // anotherBlock = ^(void) {4192 // myImportedBlock(); // import and invoke the closure4193 // };4194 //4195 if (isTopLevelBlockPointerType(VD->getType())) {4196 S += "struct __block_impl *";4197 Constructor += ", void *" + ArgName;4198 } else {4199 QualType QT = VD->getType();4200 if (HasLocalVariableExternalStorage(VD))4201 QT = Context->getPointerType(QT);4202 QT.getAsStringInternal(FieldName, Context->getPrintingPolicy());4203 QT.getAsStringInternal(ArgName, Context->getPrintingPolicy());4204 Constructor += ", " + ArgName;4205 }4206 S += FieldName + ";\n";4207 }4208 // Output all "by ref" declarations.4209 for (ValueDecl *VD : BlockByRefDecls) {4210 S += " ";4211 std::string FieldName = VD->getNameAsString();4212 std::string ArgName = "_" + FieldName;4213 {4214 std::string TypeString;4215 RewriteByRefString(TypeString, FieldName, VD);4216 TypeString += " *";4217 FieldName = TypeString + FieldName;4218 ArgName = TypeString + ArgName;4219 Constructor += ", " + ArgName;4220 }4221 S += FieldName + "; // by ref\n";4222 }4223 // Finish writing the constructor.4224 Constructor += ", int flags=0)";4225 // Initialize all "by copy" arguments.4226 bool firsTime = true;4227 for (const ValueDecl *VD : BlockByCopyDecls) {4228 std::string Name = VD->getNameAsString();4229 if (firsTime) {4230 Constructor += " : ";4231 firsTime = false;4232 } else4233 Constructor += ", ";4234 if (isTopLevelBlockPointerType(VD->getType()))4235 Constructor += Name + "((struct __block_impl *)_" + Name + ")";4236 else4237 Constructor += Name + "(_" + Name + ")";4238 }4239 // Initialize all "by ref" arguments.4240 for (const ValueDecl *VD : BlockByRefDecls) {4241 std::string Name = VD->getNameAsString();4242 if (firsTime) {4243 Constructor += " : ";4244 firsTime = false;4245 }4246 else4247 Constructor += ", ";4248 Constructor += Name + "(_" + Name + "->__forwarding)";4249 }4250 4251 Constructor += " {\n";4252 if (GlobalVarDecl)4253 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";4254 else4255 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";4256 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";4257 4258 Constructor += " Desc = desc;\n";4259 } else {4260 // Finish writing the constructor.4261 Constructor += ", int flags=0) {\n";4262 if (GlobalVarDecl)4263 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n";4264 else4265 Constructor += " impl.isa = &_NSConcreteStackBlock;\n";4266 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n";4267 Constructor += " Desc = desc;\n";4268 }4269 Constructor += " ";4270 Constructor += "}\n";4271 S += Constructor;4272 S += "};\n";4273 return S;4274}4275 4276std::string RewriteModernObjC::SynthesizeBlockDescriptor(4277 const std::string &DescTag, const std::string &ImplTag, int i,4278 StringRef FunName, unsigned hasCopy) {4279 std::string S = "\nstatic struct " + DescTag;4280 4281 S += " {\n size_t reserved;\n";4282 S += " size_t Block_size;\n";4283 if (hasCopy) {4284 S += " void (*copy)(struct ";4285 S += ImplTag; S += "*, struct ";4286 S += ImplTag; S += "*);\n";4287 4288 S += " void (*dispose)(struct ";4289 S += ImplTag; S += "*);\n";4290 }4291 S += "} ";4292 4293 S += DescTag + "_DATA = { 0, sizeof(struct ";4294 S += ImplTag + ")";4295 if (hasCopy) {4296 S += ", __" + FunName.str() + "_block_copy_" + utostr(i);4297 S += ", __" + FunName.str() + "_block_dispose_" + utostr(i);4298 }4299 S += "};\n";4300 return S;4301}4302 4303void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart,4304 StringRef FunName) {4305 bool RewriteSC = (GlobalVarDecl &&4306 !Blocks.empty() &&4307 GlobalVarDecl->getStorageClass() == SC_Static &&4308 GlobalVarDecl->getType().getCVRQualifiers());4309 if (RewriteSC) {4310 std::string SC(" void __");4311 SC += GlobalVarDecl->getNameAsString();4312 SC += "() {}";4313 InsertText(FunLocStart, SC);4314 }4315 4316 // Insert closures that were part of the function.4317 for (unsigned i = 0, count=0; i < Blocks.size(); i++) {4318 CollectBlockDeclRefInfo(Blocks[i]);4319 // Need to copy-in the inner copied-in variables not actually used in this4320 // block.4321 for (int j = 0; j < InnerDeclRefsCount[i]; j++) {4322 DeclRefExpr *Exp = InnerDeclRefs[count++];4323 ValueDecl *VD = Exp->getDecl();4324 BlockDeclRefs.push_back(Exp);4325 if (!VD->hasAttr<BlocksAttr>()) {4326 BlockByCopyDecls.insert(VD);4327 continue;4328 }4329 4330 BlockByRefDecls.insert(VD);4331 4332 // imported objects in the inner blocks not used in the outer4333 // blocks must be copied/disposed in the outer block as well.4334 if (VD->getType()->isObjCObjectPointerType() ||4335 VD->getType()->isBlockPointerType())4336 ImportedBlockDecls.insert(VD);4337 }4338 4339 std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i);4340 std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i);4341 4342 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag);4343 4344 InsertText(FunLocStart, CI);4345 4346 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag);4347 4348 InsertText(FunLocStart, CF);4349 4350 if (ImportedBlockDecls.size()) {4351 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag);4352 InsertText(FunLocStart, HF);4353 }4354 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName,4355 ImportedBlockDecls.size() > 0);4356 InsertText(FunLocStart, BD);4357 4358 BlockDeclRefs.clear();4359 BlockByRefDecls.clear();4360 BlockByCopyDecls.clear();4361 ImportedBlockDecls.clear();4362 }4363 if (RewriteSC) {4364 // Must insert any 'const/volatile/static here. Since it has been4365 // removed as result of rewriting of block literals.4366 std::string SC;4367 if (GlobalVarDecl->getStorageClass() == SC_Static)4368 SC = "static ";4369 if (GlobalVarDecl->getType().isConstQualified())4370 SC += "const ";4371 if (GlobalVarDecl->getType().isVolatileQualified())4372 SC += "volatile ";4373 if (GlobalVarDecl->getType().isRestrictQualified())4374 SC += "restrict ";4375 InsertText(FunLocStart, SC);4376 }4377 if (GlobalConstructionExp) {4378 // extra fancy dance for global literal expression.4379 4380 // Always the latest block expression on the block stack.4381 std::string Tag = "__";4382 Tag += FunName;4383 Tag += "_block_impl_";4384 Tag += utostr(Blocks.size()-1);4385 std::string globalBuf = "static ";4386 globalBuf += Tag; globalBuf += " ";4387 std::string SStr;4388 4389 llvm::raw_string_ostream constructorExprBuf(SStr);4390 GlobalConstructionExp->printPretty(constructorExprBuf, nullptr,4391 PrintingPolicy(LangOpts));4392 globalBuf += SStr;4393 globalBuf += ";\n";4394 InsertText(FunLocStart, globalBuf);4395 GlobalConstructionExp = nullptr;4396 }4397 4398 Blocks.clear();4399 InnerDeclRefsCount.clear();4400 InnerDeclRefs.clear();4401 RewrittenBlockExprs.clear();4402}4403 4404void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) {4405 SourceLocation FunLocStart =4406 (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD)4407 : FD->getTypeSpecStartLoc();4408 StringRef FuncName = FD->getName();4409 4410 SynthesizeBlockLiterals(FunLocStart, FuncName);4411}4412 4413static void BuildUniqueMethodName(std::string &Name,4414 ObjCMethodDecl *MD) {4415 ObjCInterfaceDecl *IFace = MD->getClassInterface();4416 Name = std::string(IFace->getName());4417 Name += "__" + MD->getSelector().getAsString();4418 // Convert colons to underscores.4419 std::string::size_type loc = 0;4420 while ((loc = Name.find(':', loc)) != std::string::npos)4421 Name.replace(loc, 1, "_");4422}4423 4424void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) {4425 // fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n");4426 // SourceLocation FunLocStart = MD->getBeginLoc();4427 SourceLocation FunLocStart = MD->getBeginLoc();4428 std::string FuncName;4429 BuildUniqueMethodName(FuncName, MD);4430 SynthesizeBlockLiterals(FunLocStart, FuncName);4431}4432 4433void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) {4434 for (Stmt *SubStmt : S->children())4435 if (SubStmt) {4436 if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt))4437 GetBlockDeclRefExprs(CBE->getBody());4438 else4439 GetBlockDeclRefExprs(SubStmt);4440 }4441 // Handle specific things.4442 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))4443 if (DRE->refersToEnclosingVariableOrCapture() ||4444 HasLocalVariableExternalStorage(DRE->getDecl()))4445 // FIXME: Handle enums.4446 BlockDeclRefs.push_back(DRE);4447}4448 4449void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S,4450 SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs,4451 llvm::SmallPtrSetImpl<const DeclContext *> &InnerContexts) {4452 for (Stmt *SubStmt : S->children())4453 if (SubStmt) {4454 if (BlockExpr *CBE = dyn_cast<BlockExpr>(SubStmt)) {4455 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl()));4456 GetInnerBlockDeclRefExprs(CBE->getBody(),4457 InnerBlockDeclRefs,4458 InnerContexts);4459 }4460 else4461 GetInnerBlockDeclRefExprs(SubStmt, InnerBlockDeclRefs, InnerContexts);4462 }4463 // Handle specific things.4464 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {4465 if (DRE->refersToEnclosingVariableOrCapture() ||4466 HasLocalVariableExternalStorage(DRE->getDecl())) {4467 if (!InnerContexts.count(DRE->getDecl()->getDeclContext()))4468 InnerBlockDeclRefs.push_back(DRE);4469 if (VarDecl *Var = cast<VarDecl>(DRE->getDecl()))4470 if (Var->isFunctionOrMethodVarDecl())4471 ImportedLocalExternalDecls.insert(Var);4472 }4473 }4474}4475 4476/// convertObjCTypeToCStyleType - This routine converts such objc types4477/// as qualified objects, and blocks to their closest c/c++ types that4478/// it can. It returns true if input type was modified.4479bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) {4480 QualType oldT = T;4481 convertBlockPointerToFunctionPointer(T);4482 if (T->isFunctionPointerType()) {4483 QualType PointeeTy;4484 if (const PointerType* PT = T->getAs<PointerType>()) {4485 PointeeTy = PT->getPointeeType();4486 if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) {4487 T = convertFunctionTypeOfBlocks(FT);4488 T = Context->getPointerType(T);4489 }4490 }4491 }4492 4493 convertToUnqualifiedObjCType(T);4494 return T != oldT;4495}4496 4497/// convertFunctionTypeOfBlocks - This routine converts a function type4498/// whose result type may be a block pointer or whose argument type(s)4499/// might be block pointers to an equivalent function type replacing4500/// all block pointers to function pointers.4501QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) {4502 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);4503 // FTP will be null for closures that don't take arguments.4504 // Generate a funky cast.4505 SmallVector<QualType, 8> ArgTypes;4506 QualType Res = FT->getReturnType();4507 bool modified = convertObjCTypeToCStyleType(Res);4508 4509 if (FTP) {4510 for (auto &I : FTP->param_types()) {4511 QualType t = I;4512 // Make sure we convert "t (^)(...)" to "t (*)(...)".4513 if (convertObjCTypeToCStyleType(t))4514 modified = true;4515 ArgTypes.push_back(t);4516 }4517 }4518 QualType FuncType;4519 if (modified)4520 FuncType = getSimpleFunctionType(Res, ArgTypes);4521 else FuncType = QualType(FT, 0);4522 return FuncType;4523}4524 4525Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) {4526 // Navigate to relevant type information.4527 const BlockPointerType *CPT = nullptr;4528 4529 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) {4530 CPT = DRE->getType()->getAs<BlockPointerType>();4531 } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) {4532 CPT = MExpr->getType()->getAs<BlockPointerType>();4533 }4534 else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) {4535 return SynthesizeBlockCall(Exp, PRE->getSubExpr());4536 }4537 else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp))4538 CPT = IEXPR->getType()->getAs<BlockPointerType>();4539 else if (const ConditionalOperator *CEXPR =4540 dyn_cast<ConditionalOperator>(BlockExp)) {4541 Expr *LHSExp = CEXPR->getLHS();4542 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp);4543 Expr *RHSExp = CEXPR->getRHS();4544 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp);4545 Expr *CONDExp = CEXPR->getCond();4546 ConditionalOperator *CondExpr = new (Context) ConditionalOperator(4547 CONDExp, SourceLocation(), cast<Expr>(LHSStmt), SourceLocation(),4548 cast<Expr>(RHSStmt), Exp->getType(), VK_PRValue, OK_Ordinary);4549 return CondExpr;4550 } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) {4551 CPT = IRE->getType()->getAs<BlockPointerType>();4552 } else if (const PseudoObjectExpr *POE4553 = dyn_cast<PseudoObjectExpr>(BlockExp)) {4554 CPT = POE->getType()->castAs<BlockPointerType>();4555 } else {4556 assert(false && "RewriteBlockClass: Bad type");4557 }4558 assert(CPT && "RewriteBlockClass: Bad type");4559 const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>();4560 assert(FT && "RewriteBlockClass: Bad type");4561 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT);4562 // FTP will be null for closures that don't take arguments.4563 4564 RecordDecl *RD = RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,4565 SourceLocation(), SourceLocation(),4566 &Context->Idents.get("__block_impl"));4567 QualType PtrBlock = Context->getPointerType(Context->getCanonicalTagType(RD));4568 4569 // Generate a funky cast.4570 SmallVector<QualType, 8> ArgTypes;4571 4572 // Push the block argument type.4573 ArgTypes.push_back(PtrBlock);4574 if (FTP) {4575 for (auto &I : FTP->param_types()) {4576 QualType t = I;4577 // Make sure we convert "t (^)(...)" to "t (*)(...)".4578 if (!convertBlockPointerToFunctionPointer(t))4579 convertToUnqualifiedObjCType(t);4580 ArgTypes.push_back(t);4581 }4582 }4583 // Now do the pointer to function cast.4584 QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes);4585 4586 PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType);4587 4588 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock,4589 CK_BitCast,4590 const_cast<Expr*>(BlockExp));4591 // Don't forget the parens to enforce the proper binding.4592 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),4593 BlkCast);4594 //PE->dump();4595 4596 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),4597 SourceLocation(),4598 &Context->Idents.get("FuncPtr"),4599 Context->VoidPtrTy, nullptr,4600 /*BitWidth=*/nullptr, /*Mutable=*/true,4601 ICIS_NoInit);4602 MemberExpr *ME = MemberExpr::CreateImplicit(4603 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);4604 4605 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType,4606 CK_BitCast, ME);4607 PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast);4608 4609 SmallVector<Expr*, 8> BlkExprs;4610 // Add the implicit argument.4611 BlkExprs.push_back(BlkCast);4612 // Add the user arguments.4613 for (CallExpr::arg_iterator I = Exp->arg_begin(),4614 E = Exp->arg_end(); I != E; ++I) {4615 BlkExprs.push_back(*I);4616 }4617 CallExpr *CE =4618 CallExpr::Create(*Context, PE, BlkExprs, Exp->getType(), VK_PRValue,4619 SourceLocation(), FPOptionsOverride());4620 return CE;4621}4622 4623// We need to return the rewritten expression to handle cases where the4624// DeclRefExpr is embedded in another expression being rewritten.4625// For example:4626//4627// int main() {4628// __block Foo *f;4629// __block int i;4630//4631// void (^myblock)() = ^() {4632// [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten).4633// i = 77;4634// };4635//}4636Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) {4637 // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR4638 // for each DeclRefExp where BYREFVAR is name of the variable.4639 ValueDecl *VD = DeclRefExp->getDecl();4640 bool isArrow = DeclRefExp->refersToEnclosingVariableOrCapture() ||4641 HasLocalVariableExternalStorage(DeclRefExp->getDecl());4642 4643 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),4644 SourceLocation(),4645 &Context->Idents.get("__forwarding"),4646 Context->VoidPtrTy, nullptr,4647 /*BitWidth=*/nullptr, /*Mutable=*/true,4648 ICIS_NoInit);4649 MemberExpr *ME = MemberExpr::CreateImplicit(4650 *Context, DeclRefExp, isArrow, FD, FD->getType(), VK_LValue, OK_Ordinary);4651 4652 StringRef Name = VD->getName();4653 FD = FieldDecl::Create(*Context, nullptr, SourceLocation(), SourceLocation(),4654 &Context->Idents.get(Name),4655 Context->VoidPtrTy, nullptr,4656 /*BitWidth=*/nullptr, /*Mutable=*/true,4657 ICIS_NoInit);4658 ME = MemberExpr::CreateImplicit(*Context, ME, true, FD, DeclRefExp->getType(),4659 VK_LValue, OK_Ordinary);4660 4661 // Need parens to enforce precedence.4662 ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(),4663 DeclRefExp->getExprLoc(),4664 ME);4665 ReplaceStmt(DeclRefExp, PE);4666 return PE;4667}4668 4669// Rewrites the imported local variable V with external storage4670// (static, extern, etc.) as *V4671//4672Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {4673 ValueDecl *VD = DRE->getDecl();4674 if (VarDecl *Var = dyn_cast<VarDecl>(VD))4675 if (!ImportedLocalExternalDecls.count(Var))4676 return DRE;4677 Expr *Exp = UnaryOperator::Create(4678 const_cast<ASTContext &>(*Context), DRE, UO_Deref, DRE->getType(),4679 VK_LValue, OK_Ordinary, DRE->getLocation(), false, FPOptionsOverride());4680 // Need parens to enforce precedence.4681 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),4682 Exp);4683 ReplaceStmt(DRE, PE);4684 return PE;4685}4686 4687void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) {4688 SourceLocation LocStart = CE->getLParenLoc();4689 SourceLocation LocEnd = CE->getRParenLoc();4690 4691 // Need to avoid trying to rewrite synthesized casts.4692 if (LocStart.isInvalid())4693 return;4694 // Need to avoid trying to rewrite casts contained in macros.4695 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd))4696 return;4697 4698 const char *startBuf = SM->getCharacterData(LocStart);4699 const char *endBuf = SM->getCharacterData(LocEnd);4700 QualType QT = CE->getType();4701 const Type* TypePtr = QT->getAs<Type>();4702 if (isa<TypeOfExprType>(TypePtr)) {4703 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr);4704 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType();4705 std::string TypeAsString = "(";4706 RewriteBlockPointerType(TypeAsString, QT);4707 TypeAsString += ")";4708 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString);4709 return;4710 }4711 // advance the location to startArgList.4712 const char *argPtr = startBuf;4713 4714 while (*argPtr++ && (argPtr < endBuf)) {4715 switch (*argPtr) {4716 case '^':4717 // Replace the '^' with '*'.4718 LocStart = LocStart.getLocWithOffset(argPtr-startBuf);4719 ReplaceText(LocStart, 1, "*");4720 break;4721 }4722 }4723}4724 4725void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) {4726 CastKind CastKind = IC->getCastKind();4727 if (CastKind != CK_BlockPointerToObjCPointerCast &&4728 CastKind != CK_AnyPointerToBlockPointerCast)4729 return;4730 4731 QualType QT = IC->getType();4732 (void)convertBlockPointerToFunctionPointer(QT);4733 std::string TypeString(QT.getAsString(Context->getPrintingPolicy()));4734 std::string Str = "(";4735 Str += TypeString;4736 Str += ")";4737 InsertText(IC->getSubExpr()->getBeginLoc(), Str);4738}4739 4740void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) {4741 SourceLocation DeclLoc = FD->getLocation();4742 unsigned parenCount = 0;4743 4744 // We have 1 or more arguments that have closure pointers.4745 const char *startBuf = SM->getCharacterData(DeclLoc);4746 const char *startArgList = strchr(startBuf, '(');4747 4748 assert((*startArgList == '(') && "Rewriter fuzzy parser confused");4749 4750 parenCount++;4751 // advance the location to startArgList.4752 DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf);4753 assert((DeclLoc.isValid()) && "Invalid DeclLoc");4754 4755 const char *argPtr = startArgList;4756 4757 while (*argPtr++ && parenCount) {4758 switch (*argPtr) {4759 case '^':4760 // Replace the '^' with '*'.4761 DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList);4762 ReplaceText(DeclLoc, 1, "*");4763 break;4764 case '(':4765 parenCount++;4766 break;4767 case ')':4768 parenCount--;4769 break;4770 }4771 }4772}4773 4774bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) {4775 const FunctionProtoType *FTP;4776 const PointerType *PT = QT->getAs<PointerType>();4777 if (PT) {4778 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();4779 } else {4780 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();4781 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");4782 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();4783 }4784 if (FTP) {4785 for (const auto &I : FTP->param_types())4786 if (isTopLevelBlockPointerType(I))4787 return true;4788 }4789 return false;4790}4791 4792bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) {4793 const FunctionProtoType *FTP;4794 const PointerType *PT = QT->getAs<PointerType>();4795 if (PT) {4796 FTP = PT->getPointeeType()->getAs<FunctionProtoType>();4797 } else {4798 const BlockPointerType *BPT = QT->getAs<BlockPointerType>();4799 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");4800 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>();4801 }4802 if (FTP) {4803 for (const auto &I : FTP->param_types()) {4804 if (I->isObjCQualifiedIdType())4805 return true;4806 if (I->isObjCObjectPointerType() &&4807 I->getPointeeType()->isObjCQualifiedInterfaceType())4808 return true;4809 }4810 4811 }4812 return false;4813}4814 4815void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen,4816 const char *&RParen) {4817 const char *argPtr = strchr(Name, '(');4818 assert((*argPtr == '(') && "Rewriter fuzzy parser confused");4819 4820 LParen = argPtr; // output the start.4821 argPtr++; // skip past the left paren.4822 unsigned parenCount = 1;4823 4824 while (*argPtr && parenCount) {4825 switch (*argPtr) {4826 case '(': parenCount++; break;4827 case ')': parenCount--; break;4828 default: break;4829 }4830 if (parenCount) argPtr++;4831 }4832 assert((*argPtr == ')') && "Rewriter fuzzy parser confused");4833 RParen = argPtr; // output the end4834}4835 4836void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) {4837 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {4838 RewriteBlockPointerFunctionArgs(FD);4839 return;4840 }4841 // Handle Variables and Typedefs.4842 SourceLocation DeclLoc = ND->getLocation();4843 QualType DeclT;4844 if (VarDecl *VD = dyn_cast<VarDecl>(ND))4845 DeclT = VD->getType();4846 else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))4847 DeclT = TDD->getUnderlyingType();4848 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))4849 DeclT = FD->getType();4850 else4851 llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled");4852 4853 const char *startBuf = SM->getCharacterData(DeclLoc);4854 const char *endBuf = startBuf;4855 // scan backward (from the decl location) for the end of the previous decl.4856 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)4857 startBuf--;4858 SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf);4859 std::string buf;4860 unsigned OrigLength=0;4861 // *startBuf != '^' if we are dealing with a pointer to function that4862 // may take block argument types (which will be handled below).4863 if (*startBuf == '^') {4864 // Replace the '^' with '*', computing a negative offset.4865 buf = '*';4866 startBuf++;4867 OrigLength++;4868 }4869 while (*startBuf != ')') {4870 buf += *startBuf;4871 startBuf++;4872 OrigLength++;4873 }4874 buf += ')';4875 OrigLength++;4876 4877 if (PointerTypeTakesAnyBlockArguments(DeclT) ||4878 PointerTypeTakesAnyObjCQualifiedType(DeclT)) {4879 // Replace the '^' with '*' for arguments.4880 // Replace id<P> with id/*<>*/4881 DeclLoc = ND->getLocation();4882 startBuf = SM->getCharacterData(DeclLoc);4883 const char *argListBegin, *argListEnd;4884 GetExtentOfArgList(startBuf, argListBegin, argListEnd);4885 while (argListBegin < argListEnd) {4886 if (*argListBegin == '^')4887 buf += '*';4888 else if (*argListBegin == '<') {4889 buf += "/*";4890 buf += *argListBegin++;4891 OrigLength++;4892 while (*argListBegin != '>') {4893 buf += *argListBegin++;4894 OrigLength++;4895 }4896 buf += *argListBegin;4897 buf += "*/";4898 }4899 else4900 buf += *argListBegin;4901 argListBegin++;4902 OrigLength++;4903 }4904 buf += ')';4905 OrigLength++;4906 }4907 ReplaceText(Start, OrigLength, buf);4908}4909 4910/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes:4911/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst,4912/// struct Block_byref_id_object *src) {4913/// _Block_object_assign (&_dest->object, _src->object,4914/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4915/// [|BLOCK_FIELD_IS_WEAK]) // object4916/// _Block_object_assign(&_dest->object, _src->object,4917/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4918/// [|BLOCK_FIELD_IS_WEAK]) // block4919/// }4920/// And:4921/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) {4922/// _Block_object_dispose(_src->object,4923/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT4924/// [|BLOCK_FIELD_IS_WEAK]) // object4925/// _Block_object_dispose(_src->object,4926/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK4927/// [|BLOCK_FIELD_IS_WEAK]) // block4928/// }4929 4930std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD,4931 int flag) {4932 std::string S;4933 if (CopyDestroyCache.count(flag))4934 return S;4935 CopyDestroyCache.insert(flag);4936 S = "static void __Block_byref_id_object_copy_";4937 S += utostr(flag);4938 S += "(void *dst, void *src) {\n";4939 4940 // offset into the object pointer is computed as:4941 // void * + void* + int + int + void* + void *4942 unsigned IntSize =4943 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));4944 unsigned VoidPtrSize =4945 static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy));4946 4947 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth();4948 S += " _Block_object_assign((char*)dst + ";4949 S += utostr(offset);4950 S += ", *(void * *) ((char*)src + ";4951 S += utostr(offset);4952 S += "), ";4953 S += utostr(flag);4954 S += ");\n}\n";4955 4956 S += "static void __Block_byref_id_object_dispose_";4957 S += utostr(flag);4958 S += "(void *src) {\n";4959 S += " _Block_object_dispose(*(void * *) ((char*)src + ";4960 S += utostr(offset);4961 S += "), ";4962 S += utostr(flag);4963 S += ");\n}\n";4964 return S;4965}4966 4967/// RewriteByRefVar - For each __block typex ND variable this routine transforms4968/// the declaration into:4969/// struct __Block_byref_ND {4970/// void *__isa; // NULL for everything except __weak pointers4971/// struct __Block_byref_ND *__forwarding;4972/// int32_t __flags;4973/// int32_t __size;4974/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object4975/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object4976/// typex ND;4977/// };4978///4979/// It then replaces declaration of ND variable with:4980/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag,4981/// __size=sizeof(struct __Block_byref_ND),4982/// ND=initializer-if-any};4983///4984///4985void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl,4986 bool lastDecl) {4987 int flag = 0;4988 int isa = 0;4989 SourceLocation DeclLoc = ND->getTypeSpecStartLoc();4990 if (DeclLoc.isInvalid())4991 // If type location is missing, it is because of missing type (a warning).4992 // Use variable's location which is good for this case.4993 DeclLoc = ND->getLocation();4994 const char *startBuf = SM->getCharacterData(DeclLoc);4995 SourceLocation X = ND->getEndLoc();4996 X = SM->getExpansionLoc(X);4997 const char *endBuf = SM->getCharacterData(X);4998 std::string Name(ND->getNameAsString());4999 std::string ByrefType;5000 RewriteByRefString(ByrefType, Name, ND, true);5001 ByrefType += " {\n";5002 ByrefType += " void *__isa;\n";5003 RewriteByRefString(ByrefType, Name, ND);5004 ByrefType += " *__forwarding;\n";5005 ByrefType += " int __flags;\n";5006 ByrefType += " int __size;\n";5007 // Add void *__Block_byref_id_object_copy;5008 // void *__Block_byref_id_object_dispose; if needed.5009 QualType Ty = ND->getType();5010 bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND);5011 if (HasCopyAndDispose) {5012 ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n";5013 ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n";5014 }5015 5016 QualType T = Ty;5017 (void)convertBlockPointerToFunctionPointer(T);5018 T.getAsStringInternal(Name, Context->getPrintingPolicy());5019 5020 ByrefType += " " + Name + ";\n";5021 ByrefType += "};\n";5022 // Insert this type in global scope. It is needed by helper function.5023 SourceLocation FunLocStart;5024 if (CurFunctionDef)5025 FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef);5026 else {5027 assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null");5028 FunLocStart = CurMethodDef->getBeginLoc();5029 }5030 InsertText(FunLocStart, ByrefType);5031 5032 if (Ty.isObjCGCWeak()) {5033 flag |= BLOCK_FIELD_IS_WEAK;5034 isa = 1;5035 }5036 if (HasCopyAndDispose) {5037 flag = BLOCK_BYREF_CALLER;5038 QualType Ty = ND->getType();5039 // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well.5040 if (Ty->isBlockPointerType())5041 flag |= BLOCK_FIELD_IS_BLOCK;5042 else5043 flag |= BLOCK_FIELD_IS_OBJECT;5044 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag);5045 if (!HF.empty())5046 Preamble += HF;5047 }5048 5049 // struct __Block_byref_ND ND =5050 // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND),5051 // initializer-if-any};5052 bool hasInit = (ND->getInit() != nullptr);5053 // FIXME. rewriter does not support __block c++ objects which5054 // require construction.5055 if (hasInit)5056 if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) {5057 CXXConstructorDecl *CXXDecl = CExp->getConstructor();5058 if (CXXDecl && CXXDecl->isDefaultConstructor())5059 hasInit = false;5060 }5061 5062 unsigned flags = 0;5063 if (HasCopyAndDispose)5064 flags |= BLOCK_HAS_COPY_DISPOSE;5065 Name = ND->getNameAsString();5066 ByrefType.clear();5067 RewriteByRefString(ByrefType, Name, ND);5068 std::string ForwardingCastType("(");5069 ForwardingCastType += ByrefType + " *)";5070 ByrefType += " " + Name + " = {(void*)";5071 ByrefType += utostr(isa);5072 ByrefType += "," + ForwardingCastType + "&" + Name + ", ";5073 ByrefType += utostr(flags);5074 ByrefType += ", ";5075 ByrefType += "sizeof(";5076 RewriteByRefString(ByrefType, Name, ND);5077 ByrefType += ")";5078 if (HasCopyAndDispose) {5079 ByrefType += ", __Block_byref_id_object_copy_";5080 ByrefType += utostr(flag);5081 ByrefType += ", __Block_byref_id_object_dispose_";5082 ByrefType += utostr(flag);5083 }5084 5085 if (!firstDecl) {5086 // In multiple __block declarations, and for all but 1st declaration,5087 // find location of the separating comma. This would be start location5088 // where new text is to be inserted.5089 DeclLoc = ND->getLocation();5090 const char *startDeclBuf = SM->getCharacterData(DeclLoc);5091 const char *commaBuf = startDeclBuf;5092 while (*commaBuf != ',')5093 commaBuf--;5094 assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','");5095 DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf);5096 startBuf = commaBuf;5097 }5098 5099 if (!hasInit) {5100 ByrefType += "};\n";5101 unsigned nameSize = Name.size();5102 // for block or function pointer declaration. Name is already5103 // part of the declaration.5104 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType())5105 nameSize = 1;5106 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType);5107 }5108 else {5109 ByrefType += ", ";5110 SourceLocation startLoc;5111 Expr *E = ND->getInit();5112 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E))5113 startLoc = ECE->getLParenLoc();5114 else5115 startLoc = E->getBeginLoc();5116 startLoc = SM->getExpansionLoc(startLoc);5117 endBuf = SM->getCharacterData(startLoc);5118 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType);5119 5120 const char separator = lastDecl ? ';' : ',';5121 const char *startInitializerBuf = SM->getCharacterData(startLoc);5122 const char *separatorBuf = strchr(startInitializerBuf, separator);5123 assert((*separatorBuf == separator) &&5124 "RewriteByRefVar: can't find ';' or ','");5125 SourceLocation separatorLoc =5126 startLoc.getLocWithOffset(separatorBuf-startInitializerBuf);5127 5128 InsertText(separatorLoc, lastDecl ? "}" : "};\n");5129 }5130}5131 5132void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) {5133 // Add initializers for any closure decl refs.5134 GetBlockDeclRefExprs(Exp->getBody());5135 if (BlockDeclRefs.size()) {5136 // Unique all "by copy" declarations.5137 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5138 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())5139 BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl());5140 // Unique all "by ref" declarations.5141 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5142 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>())5143 BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl());5144 // Find any imported blocks...they will need special attention.5145 for (unsigned i = 0; i < BlockDeclRefs.size(); i++)5146 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||5147 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||5148 BlockDeclRefs[i]->getType()->isBlockPointerType())5149 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl());5150 }5151}5152 5153FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) {5154 IdentifierInfo *ID = &Context->Idents.get(name);5155 QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy);5156 return FunctionDecl::Create(*Context, TUDecl, SourceLocation(),5157 SourceLocation(), ID, FType, nullptr, SC_Extern,5158 false, false);5159}5160 5161Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp,5162 const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) {5163 const BlockDecl *block = Exp->getBlockDecl();5164 5165 Blocks.push_back(Exp);5166 5167 CollectBlockDeclRefInfo(Exp);5168 5169 // Add inner imported variables now used in current block.5170 int countOfInnerDecls = 0;5171 if (!InnerBlockDeclRefs.empty()) {5172 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) {5173 DeclRefExpr *Exp = InnerBlockDeclRefs[i];5174 ValueDecl *VD = Exp->getDecl();5175 if (!VD->hasAttr<BlocksAttr>() && BlockByCopyDecls.insert(VD)) {5176 // We need to save the copied-in variables in nested5177 // blocks because it is needed at the end for some of the API5178 // generations. See SynthesizeBlockLiterals routine.5179 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;5180 BlockDeclRefs.push_back(Exp);5181 }5182 if (VD->hasAttr<BlocksAttr>() && BlockByRefDecls.insert(VD)) {5183 InnerDeclRefs.push_back(Exp); countOfInnerDecls++;5184 BlockDeclRefs.push_back(Exp);5185 }5186 }5187 // Find any imported blocks...they will need special attention.5188 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++)5189 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() ||5190 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() ||5191 InnerBlockDeclRefs[i]->getType()->isBlockPointerType())5192 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl());5193 }5194 InnerDeclRefsCount.push_back(countOfInnerDecls);5195 5196 std::string FuncName;5197 5198 if (CurFunctionDef)5199 FuncName = CurFunctionDef->getNameAsString();5200 else if (CurMethodDef)5201 BuildUniqueMethodName(FuncName, CurMethodDef);5202 else if (GlobalVarDecl)5203 FuncName = std::string(GlobalVarDecl->getNameAsString());5204 5205 bool GlobalBlockExpr =5206 block->getDeclContext()->getRedeclContext()->isFileContext();5207 5208 if (GlobalBlockExpr && !GlobalVarDecl) {5209 Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag);5210 GlobalBlockExpr = false;5211 }5212 5213 std::string BlockNumber = utostr(Blocks.size()-1);5214 5215 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber;5216 5217 // Get a pointer to the function type so we can cast appropriately.5218 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType());5219 QualType FType = Context->getPointerType(BFT);5220 5221 FunctionDecl *FD;5222 Expr *NewRep;5223 5224 // Simulate a constructor call...5225 std::string Tag;5226 5227 if (GlobalBlockExpr)5228 Tag = "__global_";5229 else5230 Tag = "__";5231 Tag += FuncName + "_block_impl_" + BlockNumber;5232 5233 FD = SynthBlockInitFunctionDecl(Tag);5234 DeclRefExpr *DRE = new (Context)5235 DeclRefExpr(*Context, FD, false, FType, VK_PRValue, SourceLocation());5236 5237 SmallVector<Expr*, 4> InitExprs;5238 5239 // Initialize the block function.5240 FD = SynthBlockInitFunctionDecl(Func);5241 DeclRefExpr *Arg = new (Context) DeclRefExpr(5242 *Context, FD, false, FD->getType(), VK_LValue, SourceLocation());5243 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,5244 CK_BitCast, Arg);5245 InitExprs.push_back(castExpr);5246 5247 // Initialize the block descriptor.5248 std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA";5249 5250 VarDecl *NewVD = VarDecl::Create(5251 *Context, TUDecl, SourceLocation(), SourceLocation(),5252 &Context->Idents.get(DescData), Context->VoidPtrTy, nullptr, SC_Static);5253 UnaryOperator *DescRefExpr = UnaryOperator::Create(5254 const_cast<ASTContext &>(*Context),5255 new (Context) DeclRefExpr(*Context, NewVD, false, Context->VoidPtrTy,5256 VK_LValue, SourceLocation()),5257 UO_AddrOf, Context->getPointerType(Context->VoidPtrTy), VK_PRValue,5258 OK_Ordinary, SourceLocation(), false, FPOptionsOverride());5259 InitExprs.push_back(DescRefExpr);5260 5261 // Add initializers for any closure decl refs.5262 if (BlockDeclRefs.size()) {5263 Expr *Exp;5264 // Output all "by copy" declarations.5265 for (ValueDecl *VD : BlockByCopyDecls) {5266 if (isObjCType(VD->getType())) {5267 // FIXME: Conform to ABI ([[obj retain] autorelease]).5268 FD = SynthBlockInitFunctionDecl(VD->getName());5269 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5270 VK_LValue, SourceLocation());5271 if (HasLocalVariableExternalStorage(VD)) {5272 QualType QT = VD->getType();5273 QT = Context->getPointerType(QT);5274 Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,5275 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,5276 SourceLocation(), false,5277 FPOptionsOverride());5278 }5279 } else if (isTopLevelBlockPointerType(VD->getType())) {5280 FD = SynthBlockInitFunctionDecl(VD->getName());5281 Arg = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5282 VK_LValue, SourceLocation());5283 Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy,5284 CK_BitCast, Arg);5285 } else {5286 FD = SynthBlockInitFunctionDecl(VD->getName());5287 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5288 VK_LValue, SourceLocation());5289 if (HasLocalVariableExternalStorage(VD)) {5290 QualType QT = VD->getType();5291 QT = Context->getPointerType(QT);5292 Exp = UnaryOperator::Create(const_cast<ASTContext &>(*Context), Exp,5293 UO_AddrOf, QT, VK_PRValue, OK_Ordinary,5294 SourceLocation(), false,5295 FPOptionsOverride());5296 }5297 }5298 InitExprs.push_back(Exp);5299 }5300 // Output all "by ref" declarations.5301 for (ValueDecl *ND : BlockByRefDecls) {5302 std::string Name(ND->getNameAsString());5303 std::string RecName;5304 RewriteByRefString(RecName, Name, ND, true);5305 IdentifierInfo *II = &Context->Idents.get(RecName.c_str()5306 + sizeof("struct"));5307 RecordDecl *RD =5308 RecordDecl::Create(*Context, TagTypeKind::Struct, TUDecl,5309 SourceLocation(), SourceLocation(), II);5310 assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl");5311 QualType castT =5312 Context->getPointerType(Context->getCanonicalTagType(RD));5313 5314 FD = SynthBlockInitFunctionDecl(ND->getName());5315 Exp = new (Context) DeclRefExpr(*Context, FD, false, FD->getType(),5316 VK_LValue, SourceLocation());5317 bool isNestedCapturedVar = false;5318 for (const auto &CI : block->captures()) {5319 const VarDecl *variable = CI.getVariable();5320 if (variable == ND && CI.isNested()) {5321 assert(CI.isByRef() &&5322 "SynthBlockInitExpr - captured block variable is not byref");5323 isNestedCapturedVar = true;5324 break;5325 }5326 }5327 // captured nested byref variable has its address passed. Do not take5328 // its address again.5329 if (!isNestedCapturedVar)5330 Exp = UnaryOperator::Create(5331 const_cast<ASTContext &>(*Context), Exp, UO_AddrOf,5332 Context->getPointerType(Exp->getType()), VK_PRValue, OK_Ordinary,5333 SourceLocation(), false, FPOptionsOverride());5334 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp);5335 InitExprs.push_back(Exp);5336 }5337 }5338 if (ImportedBlockDecls.size()) {5339 // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR5340 int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR);5341 unsigned IntSize =5342 static_cast<unsigned>(Context->getTypeSize(Context->IntTy));5343 Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag),5344 Context->IntTy, SourceLocation());5345 InitExprs.push_back(FlagExp);5346 }5347 NewRep = CallExpr::Create(*Context, DRE, InitExprs, FType, VK_LValue,5348 SourceLocation(), FPOptionsOverride());5349 5350 if (GlobalBlockExpr) {5351 assert (!GlobalConstructionExp &&5352 "SynthBlockInitExpr - GlobalConstructionExp must be null");5353 GlobalConstructionExp = NewRep;5354 NewRep = DRE;5355 }5356 5357 NewRep = UnaryOperator::Create(5358 const_cast<ASTContext &>(*Context), NewRep, UO_AddrOf,5359 Context->getPointerType(NewRep->getType()), VK_PRValue, OK_Ordinary,5360 SourceLocation(), false, FPOptionsOverride());5361 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast,5362 NewRep);5363 // Put Paren around the call.5364 NewRep = new (Context) ParenExpr(SourceLocation(), SourceLocation(),5365 NewRep);5366 5367 BlockDeclRefs.clear();5368 BlockByRefDecls.clear();5369 BlockByCopyDecls.clear();5370 ImportedBlockDecls.clear();5371 return NewRep;5372}5373 5374bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) {5375 if (const ObjCForCollectionStmt * CS =5376 dyn_cast<ObjCForCollectionStmt>(Stmts.back()))5377 return CS->getElement() == DS;5378 return false;5379}5380 5381//===----------------------------------------------------------------------===//5382// Function Body / Expression rewriting5383//===----------------------------------------------------------------------===//5384 5385Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {5386 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||5387 isa<DoStmt>(S) || isa<ForStmt>(S))5388 Stmts.push_back(S);5389 else if (isa<ObjCForCollectionStmt>(S)) {5390 Stmts.push_back(S);5391 ObjCBcLabelNo.push_back(++BcLabelCount);5392 }5393 5394 // Pseudo-object operations and ivar references need special5395 // treatment because we're going to recursively rewrite them.5396 if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) {5397 if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) {5398 return RewritePropertyOrImplicitSetter(PseudoOp);5399 } else {5400 return RewritePropertyOrImplicitGetter(PseudoOp);5401 }5402 } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {5403 return RewriteObjCIvarRefExpr(IvarRefExpr);5404 }5405 else if (isa<OpaqueValueExpr>(S))5406 S = cast<OpaqueValueExpr>(S)->getSourceExpr();5407 5408 SourceRange OrigStmtRange = S->getSourceRange();5409 5410 // Perform a bottom up rewrite of all children.5411 for (Stmt *&childStmt : S->children())5412 if (childStmt) {5413 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt);5414 if (newStmt) {5415 childStmt = newStmt;5416 }5417 }5418 5419 if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) {5420 SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs;5421 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;5422 InnerContexts.insert(BE->getBlockDecl());5423 ImportedLocalExternalDecls.clear();5424 GetInnerBlockDeclRefExprs(BE->getBody(),5425 InnerBlockDeclRefs, InnerContexts);5426 // Rewrite the block body in place.5427 Stmt *SaveCurrentBody = CurrentBody;5428 CurrentBody = BE->getBody();5429 PropParentMap = nullptr;5430 // block literal on rhs of a property-dot-sytax assignment5431 // must be replaced by its synthesize ast so getRewrittenText5432 // works as expected. In this case, what actually ends up on RHS5433 // is the blockTranscribed which is the helper function for the5434 // block literal; as in: self.c = ^() {[ace ARR];};5435 bool saveDisableReplaceStmt = DisableReplaceStmt;5436 DisableReplaceStmt = false;5437 RewriteFunctionBodyOrGlobalInitializer(BE->getBody());5438 DisableReplaceStmt = saveDisableReplaceStmt;5439 CurrentBody = SaveCurrentBody;5440 PropParentMap = nullptr;5441 ImportedLocalExternalDecls.clear();5442 // Now we snarf the rewritten text and stash it away for later use.5443 std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());5444 RewrittenBlockExprs[BE] = Str;5445 5446 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs);5447 5448 //blockTranscribed->dump();5449 ReplaceStmt(S, blockTranscribed);5450 return blockTranscribed;5451 }5452 // Handle specific things.5453 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S))5454 return RewriteAtEncode(AtEncode);5455 5456 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S))5457 return RewriteAtSelector(AtSelector);5458 5459 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S))5460 return RewriteObjCStringLiteral(AtString);5461 5462 if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S))5463 return RewriteObjCBoolLiteralExpr(BoolLitExpr);5464 5465 if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S))5466 return RewriteObjCBoxedExpr(BoxedExpr);5467 5468 if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S))5469 return RewriteObjCArrayLiteralExpr(ArrayLitExpr);5470 5471 if (ObjCDictionaryLiteral *DictionaryLitExpr =5472 dyn_cast<ObjCDictionaryLiteral>(S))5473 return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr);5474 5475 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) {5476#if 05477 // Before we rewrite it, put the original message expression in a comment.5478 SourceLocation startLoc = MessExpr->getBeginLoc();5479 SourceLocation endLoc = MessExpr->getEndLoc();5480 5481 const char *startBuf = SM->getCharacterData(startLoc);5482 const char *endBuf = SM->getCharacterData(endLoc);5483 5484 std::string messString;5485 messString += "// ";5486 messString.append(startBuf, endBuf-startBuf+1);5487 messString += "\n";5488 5489 // FIXME: Missing definition of5490 // InsertText(clang::SourceLocation, char const*, unsigned int).5491 // InsertText(startLoc, messString);5492 // Tried this, but it didn't work either...5493 // ReplaceText(startLoc, 0, messString.c_str(), messString.size());5494#endif5495 return RewriteMessageExpr(MessExpr);5496 }5497 5498 if (ObjCAutoreleasePoolStmt *StmtAutoRelease =5499 dyn_cast<ObjCAutoreleasePoolStmt>(S)) {5500 return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease);5501 }5502 5503 if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S))5504 return RewriteObjCTryStmt(StmtTry);5505 5506 if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S))5507 return RewriteObjCSynchronizedStmt(StmtTry);5508 5509 if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S))5510 return RewriteObjCThrowStmt(StmtThrow);5511 5512 if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S))5513 return RewriteObjCProtocolExpr(ProtocolExp);5514 5515 if (ObjCForCollectionStmt *StmtForCollection =5516 dyn_cast<ObjCForCollectionStmt>(S))5517 return RewriteObjCForCollectionStmt(StmtForCollection,5518 OrigStmtRange.getEnd());5519 if (BreakStmt *StmtBreakStmt =5520 dyn_cast<BreakStmt>(S))5521 return RewriteBreakStmt(StmtBreakStmt);5522 if (ContinueStmt *StmtContinueStmt =5523 dyn_cast<ContinueStmt>(S))5524 return RewriteContinueStmt(StmtContinueStmt);5525 5526 // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls5527 // and cast exprs.5528 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) {5529 // FIXME: What we're doing here is modifying the type-specifier that5530 // precedes the first Decl. In the future the DeclGroup should have5531 // a separate type-specifier that we can rewrite.5532 // NOTE: We need to avoid rewriting the DeclStmt if it is within5533 // the context of an ObjCForCollectionStmt. For example:5534 // NSArray *someArray;5535 // for (id <FooProtocol> index in someArray) ;5536 // This is because RewriteObjCForCollectionStmt() does textual rewriting5537 // and it depends on the original text locations/positions.5538 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS))5539 RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin());5540 5541 // Blocks rewrite rules.5542 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();5543 DI != DE; ++DI) {5544 Decl *SD = *DI;5545 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) {5546 if (isTopLevelBlockPointerType(ND->getType()))5547 RewriteBlockPointerDecl(ND);5548 else if (ND->getType()->isFunctionPointerType())5549 CheckFunctionPointerDecl(ND->getType(), ND);5550 if (VarDecl *VD = dyn_cast<VarDecl>(SD)) {5551 if (VD->hasAttr<BlocksAttr>()) {5552 static unsigned uniqueByrefDeclCount = 0;5553 assert(!BlockByRefDeclNo.count(ND) &&5554 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");5555 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;5556 RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE));5557 }5558 else5559 RewriteTypeOfDecl(VD);5560 }5561 }5562 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {5563 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))5564 RewriteBlockPointerDecl(TD);5565 else if (TD->getUnderlyingType()->isFunctionPointerType())5566 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);5567 }5568 }5569 }5570 5571 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S))5572 RewriteObjCQualifiedInterfaceTypes(CE);5573 5574 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) ||5575 isa<DoStmt>(S) || isa<ForStmt>(S)) {5576 assert(!Stmts.empty() && "Statement stack is empty");5577 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) ||5578 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back()))5579 && "Statement stack mismatch");5580 Stmts.pop_back();5581 }5582 // Handle blocks rewriting.5583 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {5584 ValueDecl *VD = DRE->getDecl();5585 if (VD->hasAttr<BlocksAttr>())5586 return RewriteBlockDeclRefExpr(DRE);5587 if (HasLocalVariableExternalStorage(VD))5588 return RewriteLocalVariableExternalStorage(DRE);5589 }5590 5591 if (CallExpr *CE = dyn_cast<CallExpr>(S)) {5592 if (CE->getCallee()->getType()->isBlockPointerType()) {5593 Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee());5594 ReplaceStmt(S, BlockCall);5595 return BlockCall;5596 }5597 }5598 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) {5599 RewriteCastExpr(CE);5600 }5601 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {5602 RewriteImplicitCastObjCExpr(ICE);5603 }5604#if 05605 5606 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) {5607 CastExpr *Replacement = new (Context) CastExpr(ICE->getType(),5608 ICE->getSubExpr(),5609 SourceLocation());5610 // Get the new text.5611 std::string SStr;5612 llvm::raw_string_ostream Buf(SStr);5613 Replacement->printPretty(Buf);5614 const std::string &Str = Buf.str();5615 5616 printf("CAST = %s\n", &Str[0]);5617 InsertText(ICE->getSubExpr()->getBeginLoc(), Str);5618 delete S;5619 return Replacement;5620 }5621#endif5622 // Return this stmt unmodified.5623 return S;5624}5625 5626void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) {5627 for (auto *FD : RD->fields()) {5628 if (isTopLevelBlockPointerType(FD->getType()))5629 RewriteBlockPointerDecl(FD);5630 if (FD->getType()->isObjCQualifiedIdType() ||5631 FD->getType()->isObjCQualifiedInterfaceType())5632 RewriteObjCQualifiedInterfaceTypes(FD);5633 }5634}5635 5636/// HandleDeclInMainFile - This is called for each top-level decl defined in the5637/// main file of the input.5638void RewriteModernObjC::HandleDeclInMainFile(Decl *D) {5639 switch (D->getKind()) {5640 case Decl::Function: {5641 FunctionDecl *FD = cast<FunctionDecl>(D);5642 if (FD->isOverloadedOperator())5643 return;5644 5645 // Since function prototypes don't have ParmDecl's, we check the function5646 // prototype. This enables us to rewrite function declarations and5647 // definitions using the same code.5648 RewriteBlocksInFunctionProtoType(FD->getType(), FD);5649 5650 if (!FD->isThisDeclarationADefinition())5651 break;5652 5653 // FIXME: If this should support Obj-C++, support CXXTryStmt5654 if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) {5655 CurFunctionDef = FD;5656 CurrentBody = Body;5657 Body =5658 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));5659 FD->setBody(Body);5660 CurrentBody = nullptr;5661 if (PropParentMap) {5662 delete PropParentMap;5663 PropParentMap = nullptr;5664 }5665 // This synthesizes and inserts the block "impl" struct, invoke function,5666 // and any copy/dispose helper functions.5667 InsertBlockLiteralsWithinFunction(FD);5668 RewriteLineDirective(D);5669 CurFunctionDef = nullptr;5670 }5671 break;5672 }5673 case Decl::ObjCMethod: {5674 ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D);5675 if (CompoundStmt *Body = MD->getCompoundBody()) {5676 CurMethodDef = MD;5677 CurrentBody = Body;5678 Body =5679 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body));5680 MD->setBody(Body);5681 CurrentBody = nullptr;5682 if (PropParentMap) {5683 delete PropParentMap;5684 PropParentMap = nullptr;5685 }5686 InsertBlockLiteralsWithinMethod(MD);5687 RewriteLineDirective(D);5688 CurMethodDef = nullptr;5689 }5690 break;5691 }5692 case Decl::ObjCImplementation: {5693 ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D);5694 ClassImplementation.push_back(CI);5695 break;5696 }5697 case Decl::ObjCCategoryImpl: {5698 ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D);5699 CategoryImplementation.push_back(CI);5700 break;5701 }5702 case Decl::Var: {5703 VarDecl *VD = cast<VarDecl>(D);5704 RewriteObjCQualifiedInterfaceTypes(VD);5705 if (isTopLevelBlockPointerType(VD->getType()))5706 RewriteBlockPointerDecl(VD);5707 else if (VD->getType()->isFunctionPointerType()) {5708 CheckFunctionPointerDecl(VD->getType(), VD);5709 if (VD->getInit()) {5710 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {5711 RewriteCastExpr(CE);5712 }5713 }5714 } else if (VD->getType()->isRecordType()) {5715 auto *RD = VD->getType()->castAsRecordDecl();5716 if (RD->isCompleteDefinition())5717 RewriteRecordBody(RD);5718 }5719 if (VD->getInit()) {5720 GlobalVarDecl = VD;5721 CurrentBody = VD->getInit();5722 RewriteFunctionBodyOrGlobalInitializer(VD->getInit());5723 CurrentBody = nullptr;5724 if (PropParentMap) {5725 delete PropParentMap;5726 PropParentMap = nullptr;5727 }5728 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName());5729 GlobalVarDecl = nullptr;5730 5731 // This is needed for blocks.5732 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) {5733 RewriteCastExpr(CE);5734 }5735 }5736 break;5737 }5738 case Decl::TypeAlias:5739 case Decl::Typedef: {5740 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {5741 if (isTopLevelBlockPointerType(TD->getUnderlyingType()))5742 RewriteBlockPointerDecl(TD);5743 else if (TD->getUnderlyingType()->isFunctionPointerType())5744 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD);5745 else5746 RewriteObjCQualifiedInterfaceTypes(TD);5747 }5748 break;5749 }5750 case Decl::CXXRecord:5751 case Decl::Record: {5752 RecordDecl *RD = cast<RecordDecl>(D);5753 if (RD->isCompleteDefinition())5754 RewriteRecordBody(RD);5755 break;5756 }5757 default:5758 break;5759 }5760 // Nothing yet.5761}5762 5763/// Write_ProtocolExprReferencedMetadata - This routine writer out the5764/// protocol reference symbols in the for of:5765/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA.5766static void Write_ProtocolExprReferencedMetadata(ASTContext *Context,5767 ObjCProtocolDecl *PDecl,5768 std::string &Result) {5769 // Also output .objc_protorefs$B section and its meta-data.5770 if (Context->getLangOpts().MicrosoftExt)5771 Result += "static ";5772 Result += "struct _protocol_t *";5773 Result += "_OBJC_PROTOCOL_REFERENCE_$_";5774 Result += PDecl->getNameAsString();5775 Result += " = &";5776 Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();5777 Result += ";\n";5778}5779 5780void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) {5781 if (Diags.hasErrorOccurred())5782 return;5783 5784 RewriteInclude();5785 5786 for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) {5787 // translation of function bodies were postponed until all class and5788 // their extensions and implementations are seen. This is because, we5789 // cannot build grouping structs for bitfields until they are all seen.5790 FunctionDecl *FDecl = FunctionDefinitionsSeen[i];5791 HandleTopLevelSingleDecl(FDecl);5792 }5793 5794 // Here's a great place to add any extra declarations that may be needed.5795 // Write out meta data for each @protocol(<expr>).5796 for (ObjCProtocolDecl *ProtDecl : ProtocolExprDecls) {5797 RewriteObjCProtocolMetaData(ProtDecl, Preamble);5798 Write_ProtocolExprReferencedMetadata(Context, ProtDecl, Preamble);5799 }5800 5801 InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false);5802 5803 if (ClassImplementation.size() || CategoryImplementation.size())5804 RewriteImplementations();5805 5806 for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) {5807 ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i];5808 // Write struct declaration for the class matching its ivar declarations.5809 // Note that for modern abi, this is postponed until the end of TU5810 // because class extensions and the implementation might declare their own5811 // private ivars.5812 RewriteInterfaceDecl(CDecl);5813 }5814 5815 // Get the buffer corresponding to MainFileID. If we haven't changed it, then5816 // we are done.5817 if (const RewriteBuffer *RewriteBuf =5818 Rewrite.getRewriteBufferFor(MainFileID)) {5819 //printf("Changed:\n");5820 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());5821 } else {5822 llvm::errs() << "No changes\n";5823 }5824 5825 if (ClassImplementation.size() || CategoryImplementation.size() ||5826 ProtocolExprDecls.size()) {5827 // Rewrite Objective-c meta data*5828 std::string ResultStr;5829 RewriteMetaDataIntoBuffer(ResultStr);5830 // Emit metadata.5831 *OutFile << ResultStr;5832 }5833 // Emit ImageInfo;5834 {5835 std::string ResultStr;5836 WriteImageInfo(ResultStr);5837 *OutFile << ResultStr;5838 }5839 OutFile->flush();5840}5841 5842void RewriteModernObjC::Initialize(ASTContext &context) {5843 InitializeCommon(context);5844 5845 Preamble += "#ifndef __OBJC2__\n";5846 Preamble += "#define __OBJC2__\n";5847 Preamble += "#endif\n";5848 5849 // declaring objc_selector outside the parameter list removes a silly5850 // scope related warning...5851 if (IsHeader)5852 Preamble = "#pragma once\n";5853 Preamble += "struct objc_selector; struct objc_class;\n";5854 Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; ";5855 Preamble += "\n\tstruct objc_object *superClass; ";5856 // Add a constructor for creating temporary objects.5857 Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) ";5858 Preamble += ": object(o), superClass(s) {} ";5859 Preamble += "\n};\n";5860 5861 if (LangOpts.MicrosoftExt) {5862 // Define all sections using syntax that makes sense.5863 // These are currently generated.5864 Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n";5865 Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n";5866 Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n";5867 Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n";5868 Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n";5869 // These are generated but not necessary for functionality.5870 Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n";5871 Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n";5872 Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n";5873 Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n";5874 5875 // These need be generated for performance. Currently they are not,5876 // using API calls instead.5877 Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n";5878 Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n";5879 Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n";5880 5881 }5882 Preamble += "#ifndef _REWRITER_typedef_Protocol\n";5883 Preamble += "typedef struct objc_object Protocol;\n";5884 Preamble += "#define _REWRITER_typedef_Protocol\n";5885 Preamble += "#endif\n";5886 if (LangOpts.MicrosoftExt) {5887 Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";5888 Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";5889 }5890 else5891 Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";5892 5893 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n";5894 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n";5895 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n";5896 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n";5897 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n";5898 5899 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass";5900 Preamble += "(const char *);\n";5901 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass";5902 Preamble += "(struct objc_class *);\n";5903 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass";5904 Preamble += "(const char *);\n";5905 Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n";5906 // @synchronized hooks.5907 Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n";5908 Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n";5909 Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";5910 Preamble += "#ifdef _WIN64\n";5911 Preamble += "typedef unsigned long long _WIN_NSUInteger;\n";5912 Preamble += "#else\n";5913 Preamble += "typedef unsigned int _WIN_NSUInteger;\n";5914 Preamble += "#endif\n";5915 Preamble += "#ifndef __FASTENUMERATIONSTATE\n";5916 Preamble += "struct __objcFastEnumerationState {\n\t";5917 Preamble += "unsigned long state;\n\t";5918 Preamble += "void **itemsPtr;\n\t";5919 Preamble += "unsigned long *mutationsPtr;\n\t";5920 Preamble += "unsigned long extra[5];\n};\n";5921 Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";5922 Preamble += "#define __FASTENUMERATIONSTATE\n";5923 Preamble += "#endif\n";5924 Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";5925 Preamble += "struct __NSConstantStringImpl {\n";5926 Preamble += " int *isa;\n";5927 Preamble += " int flags;\n";5928 Preamble += " char *str;\n";5929 Preamble += "#if _WIN64\n";5930 Preamble += " long long length;\n";5931 Preamble += "#else\n";5932 Preamble += " long length;\n";5933 Preamble += "#endif\n";5934 Preamble += "};\n";5935 Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";5936 Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";5937 Preamble += "#else\n";5938 Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";5939 Preamble += "#endif\n";5940 Preamble += "#define __NSCONSTANTSTRINGIMPL\n";5941 Preamble += "#endif\n";5942 // Blocks preamble.5943 Preamble += "#ifndef BLOCK_IMPL\n";5944 Preamble += "#define BLOCK_IMPL\n";5945 Preamble += "struct __block_impl {\n";5946 Preamble += " void *isa;\n";5947 Preamble += " int Flags;\n";5948 Preamble += " int Reserved;\n";5949 Preamble += " void *FuncPtr;\n";5950 Preamble += "};\n";5951 Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";5952 Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";5953 Preamble += "extern \"C\" __declspec(dllexport) "5954 "void _Block_object_assign(void *, const void *, const int);\n";5955 Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";5956 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";5957 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";5958 Preamble += "#else\n";5959 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";5960 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";5961 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";5962 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";5963 Preamble += "#endif\n";5964 Preamble += "#endif\n";5965 if (LangOpts.MicrosoftExt) {5966 Preamble += "#undef __OBJC_RW_DLLIMPORT\n";5967 Preamble += "#undef __OBJC_RW_STATICIMPORT\n";5968 Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests.5969 Preamble += "#define __attribute__(X)\n";5970 Preamble += "#endif\n";5971 Preamble += "#ifndef __weak\n";5972 Preamble += "#define __weak\n";5973 Preamble += "#endif\n";5974 Preamble += "#ifndef __block\n";5975 Preamble += "#define __block\n";5976 Preamble += "#endif\n";5977 }5978 else {5979 Preamble += "#define __block\n";5980 Preamble += "#define __weak\n";5981 }5982 5983 // Declarations required for modern objective-c array and dictionary literals.5984 Preamble += "\n#include <stdarg.h>\n";5985 Preamble += "struct __NSContainer_literal {\n";5986 Preamble += " void * *arr;\n";5987 Preamble += " __NSContainer_literal (unsigned int count, ...) {\n";5988 Preamble += "\tva_list marker;\n";5989 Preamble += "\tva_start(marker, count);\n";5990 Preamble += "\tarr = new void *[count];\n";5991 Preamble += "\tfor (unsigned i = 0; i < count; i++)\n";5992 Preamble += "\t arr[i] = va_arg(marker, void *);\n";5993 Preamble += "\tva_end( marker );\n";5994 Preamble += " };\n";5995 Preamble += " ~__NSContainer_literal() {\n";5996 Preamble += "\tdelete[] arr;\n";5997 Preamble += " }\n";5998 Preamble += "};\n";5999 6000 // Declaration required for implementation of @autoreleasepool statement.6001 Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n";6002 Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n";6003 Preamble += "struct __AtAutoreleasePool {\n";6004 Preamble += " __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n";6005 Preamble += " ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n";6006 Preamble += " void * atautoreleasepoolobj;\n";6007 Preamble += "};\n";6008 6009 // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long6010 // as this avoids warning in any 64bit/32bit compilation model.6011 Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n";6012}6013 6014/// RewriteIvarOffsetComputation - This routine synthesizes computation of6015/// ivar offset.6016void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar,6017 std::string &Result) {6018 Result += "__OFFSETOFIVAR__(struct ";6019 Result += ivar->getContainingInterface()->getNameAsString();6020 if (LangOpts.MicrosoftExt)6021 Result += "_IMPL";6022 Result += ", ";6023 if (ivar->isBitField())6024 ObjCIvarBitfieldGroupDecl(ivar, Result);6025 else6026 Result += ivar->getNameAsString();6027 Result += ")";6028}6029 6030/// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI.6031/// struct _prop_t {6032/// const char *name;6033/// char *attributes;6034/// }6035 6036/// struct _prop_list_t {6037/// uint32_t entsize; // sizeof(struct _prop_t)6038/// uint32_t count_of_properties;6039/// struct _prop_t prop_list[count_of_properties];6040/// }6041 6042/// struct _protocol_t;6043 6044/// struct _protocol_list_t {6045/// long protocol_count; // Note, this is 32/64 bit6046/// struct _protocol_t * protocol_list[protocol_count];6047/// }6048 6049/// struct _objc_method {6050/// SEL _cmd;6051/// const char *method_type;6052/// char *_imp;6053/// }6054 6055/// struct _method_list_t {6056/// uint32_t entsize; // sizeof(struct _objc_method)6057/// uint32_t method_count;6058/// struct _objc_method method_list[method_count];6059/// }6060 6061/// struct _protocol_t {6062/// id isa; // NULL6063/// const char *protocol_name;6064/// const struct _protocol_list_t * protocol_list; // super protocols6065/// const struct method_list_t *instance_methods;6066/// const struct method_list_t *class_methods;6067/// const struct method_list_t *optionalInstanceMethods;6068/// const struct method_list_t *optionalClassMethods;6069/// const struct _prop_list_t * properties;6070/// const uint32_t size; // sizeof(struct _protocol_t)6071/// const uint32_t flags; // = 06072/// const char ** extendedMethodTypes;6073/// }6074 6075/// struct _ivar_t {6076/// unsigned long int *offset; // pointer to ivar offset location6077/// const char *name;6078/// const char *type;6079/// uint32_t alignment;6080/// uint32_t size;6081/// }6082 6083/// struct _ivar_list_t {6084/// uint32 entsize; // sizeof(struct _ivar_t)6085/// uint32 count;6086/// struct _ivar_t list[count];6087/// }6088 6089/// struct _class_ro_t {6090/// uint32_t flags;6091/// uint32_t instanceStart;6092/// uint32_t instanceSize;6093/// uint32_t reserved; // only when building for 64bit targets6094/// const uint8_t *ivarLayout;6095/// const char *name;6096/// const struct _method_list_t *baseMethods;6097/// const struct _protocol_list_t *baseProtocols;6098/// const struct _ivar_list_t *ivars;6099/// const uint8_t *weakIvarLayout;6100/// const struct _prop_list_t *properties;6101/// }6102 6103/// struct _class_t {6104/// struct _class_t *isa;6105/// struct _class_t *superclass;6106/// void *cache;6107/// IMP *vtable;6108/// struct _class_ro_t *ro;6109/// }6110 6111/// struct _category_t {6112/// const char *name;6113/// struct _class_t *cls;6114/// const struct _method_list_t *instance_methods;6115/// const struct _method_list_t *class_methods;6116/// const struct _protocol_list_t *protocols;6117/// const struct _prop_list_t *properties;6118/// }6119 6120/// MessageRefTy - LLVM for:6121/// struct _message_ref_t {6122/// IMP messenger;6123/// SEL name;6124/// };6125 6126/// SuperMessageRefTy - LLVM for:6127/// struct _super_message_ref_t {6128/// SUPER_IMP messenger;6129/// SEL name;6130/// };6131 6132static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) {6133 static bool meta_data_declared = false;6134 if (meta_data_declared)6135 return;6136 6137 Result += "\nstruct _prop_t {\n";6138 Result += "\tconst char *name;\n";6139 Result += "\tconst char *attributes;\n";6140 Result += "};\n";6141 6142 Result += "\nstruct _protocol_t;\n";6143 6144 Result += "\nstruct _objc_method {\n";6145 Result += "\tstruct objc_selector * _cmd;\n";6146 Result += "\tconst char *method_type;\n";6147 Result += "\tvoid *_imp;\n";6148 Result += "};\n";6149 6150 Result += "\nstruct _protocol_t {\n";6151 Result += "\tvoid * isa; // NULL\n";6152 Result += "\tconst char *protocol_name;\n";6153 Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n";6154 Result += "\tconst struct method_list_t *instance_methods;\n";6155 Result += "\tconst struct method_list_t *class_methods;\n";6156 Result += "\tconst struct method_list_t *optionalInstanceMethods;\n";6157 Result += "\tconst struct method_list_t *optionalClassMethods;\n";6158 Result += "\tconst struct _prop_list_t * properties;\n";6159 Result += "\tconst unsigned int size; // sizeof(struct _protocol_t)\n";6160 Result += "\tconst unsigned int flags; // = 0\n";6161 Result += "\tconst char ** extendedMethodTypes;\n";6162 Result += "};\n";6163 6164 Result += "\nstruct _ivar_t {\n";6165 Result += "\tunsigned long int *offset; // pointer to ivar offset location\n";6166 Result += "\tconst char *name;\n";6167 Result += "\tconst char *type;\n";6168 Result += "\tunsigned int alignment;\n";6169 Result += "\tunsigned int size;\n";6170 Result += "};\n";6171 6172 Result += "\nstruct _class_ro_t {\n";6173 Result += "\tunsigned int flags;\n";6174 Result += "\tunsigned int instanceStart;\n";6175 Result += "\tunsigned int instanceSize;\n";6176 const llvm::Triple &Triple(Context->getTargetInfo().getTriple());6177 if (Triple.getArch() == llvm::Triple::x86_64)6178 Result += "\tunsigned int reserved;\n";6179 Result += "\tconst unsigned char *ivarLayout;\n";6180 Result += "\tconst char *name;\n";6181 Result += "\tconst struct _method_list_t *baseMethods;\n";6182 Result += "\tconst struct _objc_protocol_list *baseProtocols;\n";6183 Result += "\tconst struct _ivar_list_t *ivars;\n";6184 Result += "\tconst unsigned char *weakIvarLayout;\n";6185 Result += "\tconst struct _prop_list_t *properties;\n";6186 Result += "};\n";6187 6188 Result += "\nstruct _class_t {\n";6189 Result += "\tstruct _class_t *isa;\n";6190 Result += "\tstruct _class_t *superclass;\n";6191 Result += "\tvoid *cache;\n";6192 Result += "\tvoid *vtable;\n";6193 Result += "\tstruct _class_ro_t *ro;\n";6194 Result += "};\n";6195 6196 Result += "\nstruct _category_t {\n";6197 Result += "\tconst char *name;\n";6198 Result += "\tstruct _class_t *cls;\n";6199 Result += "\tconst struct _method_list_t *instance_methods;\n";6200 Result += "\tconst struct _method_list_t *class_methods;\n";6201 Result += "\tconst struct _protocol_list_t *protocols;\n";6202 Result += "\tconst struct _prop_list_t *properties;\n";6203 Result += "};\n";6204 6205 Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n";6206 Result += "#pragma warning(disable:4273)\n";6207 meta_data_declared = true;6208}6209 6210static void Write_protocol_list_t_TypeDecl(std::string &Result,6211 long super_protocol_count) {6212 Result += "struct /*_protocol_list_t*/"; Result += " {\n";6213 Result += "\tlong protocol_count; // Note, this is 32/64 bit\n";6214 Result += "\tstruct _protocol_t *super_protocols[";6215 Result += utostr(super_protocol_count); Result += "];\n";6216 Result += "}";6217}6218 6219static void Write_method_list_t_TypeDecl(std::string &Result,6220 unsigned int method_count) {6221 Result += "struct /*_method_list_t*/"; Result += " {\n";6222 Result += "\tunsigned int entsize; // sizeof(struct _objc_method)\n";6223 Result += "\tunsigned int method_count;\n";6224 Result += "\tstruct _objc_method method_list[";6225 Result += utostr(method_count); Result += "];\n";6226 Result += "}";6227}6228 6229static void Write__prop_list_t_TypeDecl(std::string &Result,6230 unsigned int property_count) {6231 Result += "struct /*_prop_list_t*/"; Result += " {\n";6232 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";6233 Result += "\tunsigned int count_of_properties;\n";6234 Result += "\tstruct _prop_t prop_list[";6235 Result += utostr(property_count); Result += "];\n";6236 Result += "}";6237}6238 6239static void Write__ivar_list_t_TypeDecl(std::string &Result,6240 unsigned int ivar_count) {6241 Result += "struct /*_ivar_list_t*/"; Result += " {\n";6242 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n";6243 Result += "\tunsigned int count;\n";6244 Result += "\tstruct _ivar_t ivar_list[";6245 Result += utostr(ivar_count); Result += "];\n";6246 Result += "}";6247}6248 6249static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result,6250 ArrayRef<ObjCProtocolDecl *> SuperProtocols,6251 StringRef VarName,6252 StringRef ProtocolName) {6253 if (SuperProtocols.size() > 0) {6254 Result += "\nstatic ";6255 Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size());6256 Result += " "; Result += VarName;6257 Result += ProtocolName;6258 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6259 Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n";6260 for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) {6261 ObjCProtocolDecl *SuperPD = SuperProtocols[i];6262 Result += "\t&"; Result += "_OBJC_PROTOCOL_";6263 Result += SuperPD->getNameAsString();6264 if (i == e-1)6265 Result += "\n};\n";6266 else6267 Result += ",\n";6268 }6269 }6270}6271 6272static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj,6273 ASTContext *Context, std::string &Result,6274 ArrayRef<ObjCMethodDecl *> Methods,6275 StringRef VarName,6276 StringRef TopLevelDeclName,6277 bool MethodImpl) {6278 if (Methods.size() > 0) {6279 Result += "\nstatic ";6280 Write_method_list_t_TypeDecl(Result, Methods.size());6281 Result += " "; Result += VarName;6282 Result += TopLevelDeclName;6283 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6284 Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n";6285 Result += "\t"; Result += utostr(Methods.size()); Result += ",\n";6286 for (unsigned i = 0, e = Methods.size(); i < e; i++) {6287 ObjCMethodDecl *MD = Methods[i];6288 if (i == 0)6289 Result += "\t{{(struct objc_selector *)\"";6290 else6291 Result += "\t{(struct objc_selector *)\"";6292 Result += (MD)->getSelector().getAsString(); Result += "\"";6293 Result += ", ";6294 std::string MethodTypeString = Context->getObjCEncodingForMethodDecl(MD);6295 Result += "\""; Result += MethodTypeString; Result += "\"";6296 Result += ", ";6297 if (!MethodImpl)6298 Result += "0";6299 else {6300 Result += "(void *)";6301 Result += RewriteObj.MethodInternalNames[MD];6302 }6303 if (i == e-1)6304 Result += "}}\n";6305 else6306 Result += "},\n";6307 }6308 Result += "};\n";6309 }6310}6311 6312static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj,6313 ASTContext *Context, std::string &Result,6314 ArrayRef<ObjCPropertyDecl *> Properties,6315 const Decl *Container,6316 StringRef VarName,6317 StringRef ProtocolName) {6318 if (Properties.size() > 0) {6319 Result += "\nstatic ";6320 Write__prop_list_t_TypeDecl(Result, Properties.size());6321 Result += " "; Result += VarName;6322 Result += ProtocolName;6323 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6324 Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n";6325 Result += "\t"; Result += utostr(Properties.size()); Result += ",\n";6326 for (unsigned i = 0, e = Properties.size(); i < e; i++) {6327 ObjCPropertyDecl *PropDecl = Properties[i];6328 if (i == 0)6329 Result += "\t{{\"";6330 else6331 Result += "\t{\"";6332 Result += PropDecl->getName(); Result += "\",";6333 std::string PropertyTypeString =6334 Context->getObjCEncodingForPropertyDecl(PropDecl, Container);6335 std::string QuotePropertyTypeString;6336 RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString);6337 Result += "\""; Result += QuotePropertyTypeString; Result += "\"";6338 if (i == e-1)6339 Result += "}}\n";6340 else6341 Result += "},\n";6342 }6343 Result += "};\n";6344 }6345}6346 6347// Metadata flags6348enum MetaDataDlags {6349 CLS = 0x0,6350 CLS_META = 0x1,6351 CLS_ROOT = 0x2,6352 OBJC2_CLS_HIDDEN = 0x10,6353 CLS_EXCEPTION = 0x20,6354 6355 /// (Obsolete) ARC-specific: this class has a .release_ivars method6356 CLS_HAS_IVAR_RELEASER = 0x40,6357 /// class was compiled with -fobjc-arr6358 CLS_COMPILED_BY_ARC = 0x80 // (1<<7)6359};6360 6361static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result,6362 unsigned int flags,6363 const std::string &InstanceStart,6364 const std::string &InstanceSize,6365 ArrayRef<ObjCMethodDecl *>baseMethods,6366 ArrayRef<ObjCProtocolDecl *>baseProtocols,6367 ArrayRef<ObjCIvarDecl *>ivars,6368 ArrayRef<ObjCPropertyDecl *>Properties,6369 StringRef VarName,6370 StringRef ClassName) {6371 Result += "\nstatic struct _class_ro_t ";6372 Result += VarName; Result += ClassName;6373 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6374 Result += "\t";6375 Result += llvm::utostr(flags); Result += ", ";6376 Result += InstanceStart; Result += ", ";6377 Result += InstanceSize; Result += ", \n";6378 Result += "\t";6379 const llvm::Triple &Triple(Context->getTargetInfo().getTriple());6380 if (Triple.getArch() == llvm::Triple::x86_64)6381 // uint32_t const reserved; // only when building for 64bit targets6382 Result += "(unsigned int)0, \n\t";6383 // const uint8_t * const ivarLayout;6384 Result += "0, \n\t";6385 Result += "\""; Result += ClassName; Result += "\",\n\t";6386 bool metaclass = ((flags & CLS_META) != 0);6387 if (baseMethods.size() > 0) {6388 Result += "(const struct _method_list_t *)&";6389 if (metaclass)6390 Result += "_OBJC_$_CLASS_METHODS_";6391 else6392 Result += "_OBJC_$_INSTANCE_METHODS_";6393 Result += ClassName;6394 Result += ",\n\t";6395 }6396 else6397 Result += "0, \n\t";6398 6399 if (!metaclass && baseProtocols.size() > 0) {6400 Result += "(const struct _objc_protocol_list *)&";6401 Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName;6402 Result += ",\n\t";6403 }6404 else6405 Result += "0, \n\t";6406 6407 if (!metaclass && ivars.size() > 0) {6408 Result += "(const struct _ivar_list_t *)&";6409 Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName;6410 Result += ",\n\t";6411 }6412 else6413 Result += "0, \n\t";6414 6415 // weakIvarLayout6416 Result += "0, \n\t";6417 if (!metaclass && Properties.size() > 0) {6418 Result += "(const struct _prop_list_t *)&";6419 Result += "_OBJC_$_PROP_LIST_"; Result += ClassName;6420 Result += ",\n";6421 }6422 else6423 Result += "0, \n";6424 6425 Result += "};\n";6426}6427 6428static void Write_class_t(ASTContext *Context, std::string &Result,6429 StringRef VarName,6430 const ObjCInterfaceDecl *CDecl, bool metaclass) {6431 bool rootClass = (!CDecl->getSuperClass());6432 const ObjCInterfaceDecl *RootClass = CDecl;6433 6434 if (!rootClass) {6435 // Find the Root class6436 RootClass = CDecl->getSuperClass();6437 while (RootClass->getSuperClass()) {6438 RootClass = RootClass->getSuperClass();6439 }6440 }6441 6442 if (metaclass && rootClass) {6443 // Need to handle a case of use of forward declaration.6444 Result += "\n";6445 Result += "extern \"C\" ";6446 if (CDecl->getImplementation())6447 Result += "__declspec(dllexport) ";6448 else6449 Result += "__declspec(dllimport) ";6450 6451 Result += "struct _class_t OBJC_CLASS_$_";6452 Result += CDecl->getNameAsString();6453 Result += ";\n";6454 }6455 // Also, for possibility of 'super' metadata class not having been defined yet.6456 if (!rootClass) {6457 ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass();6458 Result += "\n";6459 Result += "extern \"C\" ";6460 if (SuperClass->getImplementation())6461 Result += "__declspec(dllexport) ";6462 else6463 Result += "__declspec(dllimport) ";6464 6465 Result += "struct _class_t ";6466 Result += VarName;6467 Result += SuperClass->getNameAsString();6468 Result += ";\n";6469 6470 if (metaclass && RootClass != SuperClass) {6471 Result += "extern \"C\" ";6472 if (RootClass->getImplementation())6473 Result += "__declspec(dllexport) ";6474 else6475 Result += "__declspec(dllimport) ";6476 6477 Result += "struct _class_t ";6478 Result += VarName;6479 Result += RootClass->getNameAsString();6480 Result += ";\n";6481 }6482 }6483 6484 Result += "\nextern \"C\" __declspec(dllexport) struct _class_t ";6485 Result += VarName; Result += CDecl->getNameAsString();6486 Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n";6487 Result += "\t";6488 if (metaclass) {6489 if (!rootClass) {6490 Result += "0, // &"; Result += VarName;6491 Result += RootClass->getNameAsString();6492 Result += ",\n\t";6493 Result += "0, // &"; Result += VarName;6494 Result += CDecl->getSuperClass()->getNameAsString();6495 Result += ",\n\t";6496 }6497 else {6498 Result += "0, // &"; Result += VarName;6499 Result += CDecl->getNameAsString();6500 Result += ",\n\t";6501 Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString();6502 Result += ",\n\t";6503 }6504 }6505 else {6506 Result += "0, // &OBJC_METACLASS_$_";6507 Result += CDecl->getNameAsString();6508 Result += ",\n\t";6509 if (!rootClass) {6510 Result += "0, // &"; Result += VarName;6511 Result += CDecl->getSuperClass()->getNameAsString();6512 Result += ",\n\t";6513 }6514 else6515 Result += "0,\n\t";6516 }6517 Result += "0, // (void *)&_objc_empty_cache,\n\t";6518 Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t";6519 if (metaclass)6520 Result += "&_OBJC_METACLASS_RO_$_";6521 else6522 Result += "&_OBJC_CLASS_RO_$_";6523 Result += CDecl->getNameAsString();6524 Result += ",\n};\n";6525 6526 // Add static function to initialize some of the meta-data fields.6527 // avoid doing it twice.6528 if (metaclass)6529 return;6530 6531 const ObjCInterfaceDecl *SuperClass =6532 rootClass ? CDecl : CDecl->getSuperClass();6533 6534 Result += "static void OBJC_CLASS_SETUP_$_";6535 Result += CDecl->getNameAsString();6536 Result += "(void ) {\n";6537 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6538 Result += ".isa = "; Result += "&OBJC_METACLASS_$_";6539 Result += RootClass->getNameAsString(); Result += ";\n";6540 6541 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6542 Result += ".superclass = ";6543 if (rootClass)6544 Result += "&OBJC_CLASS_$_";6545 else6546 Result += "&OBJC_METACLASS_$_";6547 6548 Result += SuperClass->getNameAsString(); Result += ";\n";6549 6550 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString();6551 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";6552 6553 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6554 Result += ".isa = "; Result += "&OBJC_METACLASS_$_";6555 Result += CDecl->getNameAsString(); Result += ";\n";6556 6557 if (!rootClass) {6558 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6559 Result += ".superclass = "; Result += "&OBJC_CLASS_$_";6560 Result += SuperClass->getNameAsString(); Result += ";\n";6561 }6562 6563 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString();6564 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n";6565 Result += "}\n";6566}6567 6568static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context,6569 std::string &Result,6570 ObjCCategoryDecl *CatDecl,6571 ObjCInterfaceDecl *ClassDecl,6572 ArrayRef<ObjCMethodDecl *> InstanceMethods,6573 ArrayRef<ObjCMethodDecl *> ClassMethods,6574 ArrayRef<ObjCProtocolDecl *> RefedProtocols,6575 ArrayRef<ObjCPropertyDecl *> ClassProperties) {6576 StringRef CatName = CatDecl->getName();6577 StringRef ClassName = ClassDecl->getName();6578 // must declare an extern class object in case this class is not implemented6579 // in this TU.6580 Result += "\n";6581 Result += "extern \"C\" ";6582 if (ClassDecl->getImplementation())6583 Result += "__declspec(dllexport) ";6584 else6585 Result += "__declspec(dllimport) ";6586 6587 Result += "struct _class_t ";6588 Result += "OBJC_CLASS_$_"; Result += ClassName;6589 Result += ";\n";6590 6591 Result += "\nstatic struct _category_t ";6592 Result += "_OBJC_$_CATEGORY_";6593 Result += ClassName; Result += "_$_"; Result += CatName;6594 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";6595 Result += "{\n";6596 Result += "\t\""; Result += ClassName; Result += "\",\n";6597 Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName;6598 Result += ",\n";6599 if (InstanceMethods.size() > 0) {6600 Result += "\t(const struct _method_list_t *)&";6601 Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_";6602 Result += ClassName; Result += "_$_"; Result += CatName;6603 Result += ",\n";6604 }6605 else6606 Result += "\t0,\n";6607 6608 if (ClassMethods.size() > 0) {6609 Result += "\t(const struct _method_list_t *)&";6610 Result += "_OBJC_$_CATEGORY_CLASS_METHODS_";6611 Result += ClassName; Result += "_$_"; Result += CatName;6612 Result += ",\n";6613 }6614 else6615 Result += "\t0,\n";6616 6617 if (RefedProtocols.size() > 0) {6618 Result += "\t(const struct _protocol_list_t *)&";6619 Result += "_OBJC_CATEGORY_PROTOCOLS_$_";6620 Result += ClassName; Result += "_$_"; Result += CatName;6621 Result += ",\n";6622 }6623 else6624 Result += "\t0,\n";6625 6626 if (ClassProperties.size() > 0) {6627 Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_";6628 Result += ClassName; Result += "_$_"; Result += CatName;6629 Result += ",\n";6630 }6631 else6632 Result += "\t0,\n";6633 6634 Result += "};\n";6635 6636 // Add static function to initialize the class pointer in the category structure.6637 Result += "static void OBJC_CATEGORY_SETUP_$_";6638 Result += ClassDecl->getNameAsString();6639 Result += "_$_";6640 Result += CatName;6641 Result += "(void ) {\n";6642 Result += "\t_OBJC_$_CATEGORY_";6643 Result += ClassDecl->getNameAsString();6644 Result += "_$_";6645 Result += CatName;6646 Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName;6647 Result += ";\n}\n";6648}6649 6650static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj,6651 ASTContext *Context, std::string &Result,6652 ArrayRef<ObjCMethodDecl *> Methods,6653 StringRef VarName,6654 StringRef ProtocolName) {6655 if (Methods.size() == 0)6656 return;6657 6658 Result += "\nstatic const char *";6659 Result += VarName; Result += ProtocolName;6660 Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n";6661 Result += "{\n";6662 for (unsigned i = 0, e = Methods.size(); i < e; i++) {6663 ObjCMethodDecl *MD = Methods[i];6664 std::string MethodTypeString =6665 Context->getObjCEncodingForMethodDecl(MD, true);6666 std::string QuoteMethodTypeString;6667 RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString);6668 Result += "\t\""; Result += QuoteMethodTypeString; Result += "\"";6669 if (i == e-1)6670 Result += "\n};\n";6671 else {6672 Result += ",\n";6673 }6674 }6675}6676 6677static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj,6678 ASTContext *Context,6679 std::string &Result,6680 ArrayRef<ObjCIvarDecl *> Ivars,6681 ObjCInterfaceDecl *CDecl) {6682 // FIXME. visibility of offset symbols may have to be set; for Darwin6683 // this is what happens:6684 /**6685 if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||6686 Ivar->getAccessControl() == ObjCIvarDecl::Package ||6687 Class->getVisibility() == HiddenVisibility)6688 Visibility should be: HiddenVisibility;6689 else6690 Visibility should be: DefaultVisibility;6691 */6692 6693 Result += "\n";6694 for (unsigned i =0, e = Ivars.size(); i < e; i++) {6695 ObjCIvarDecl *IvarDecl = Ivars[i];6696 if (Context->getLangOpts().MicrosoftExt)6697 Result += "__declspec(allocate(\".objc_ivar$B\")) ";6698 6699 if (!Context->getLangOpts().MicrosoftExt ||6700 IvarDecl->getAccessControl() == ObjCIvarDecl::Private ||6701 IvarDecl->getAccessControl() == ObjCIvarDecl::Package)6702 Result += "extern \"C\" unsigned long int ";6703 else6704 Result += "extern \"C\" __declspec(dllexport) unsigned long int ";6705 if (Ivars[i]->isBitField())6706 RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);6707 else6708 WriteInternalIvarName(CDecl, IvarDecl, Result);6709 Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))";6710 Result += " = ";6711 RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result);6712 Result += ";\n";6713 if (Ivars[i]->isBitField()) {6714 // skip over rest of the ivar bitfields.6715 SKIP_BITFIELDS(i , e, Ivars);6716 }6717 }6718}6719 6720static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj,6721 ASTContext *Context, std::string &Result,6722 ArrayRef<ObjCIvarDecl *> OriginalIvars,6723 StringRef VarName,6724 ObjCInterfaceDecl *CDecl) {6725 if (OriginalIvars.size() > 0) {6726 Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl);6727 SmallVector<ObjCIvarDecl *, 8> Ivars;6728 // strip off all but the first ivar bitfield from each group of ivars.6729 // Such ivars in the ivar list table will be replaced by their grouping struct6730 // 'ivar'.6731 for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) {6732 if (OriginalIvars[i]->isBitField()) {6733 Ivars.push_back(OriginalIvars[i]);6734 // skip over rest of the ivar bitfields.6735 SKIP_BITFIELDS(i , e, OriginalIvars);6736 }6737 else6738 Ivars.push_back(OriginalIvars[i]);6739 }6740 6741 Result += "\nstatic ";6742 Write__ivar_list_t_TypeDecl(Result, Ivars.size());6743 Result += " "; Result += VarName;6744 Result += CDecl->getNameAsString();6745 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n";6746 Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n";6747 Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n";6748 for (unsigned i =0, e = Ivars.size(); i < e; i++) {6749 ObjCIvarDecl *IvarDecl = Ivars[i];6750 if (i == 0)6751 Result += "\t{{";6752 else6753 Result += "\t {";6754 Result += "(unsigned long int *)&";6755 if (Ivars[i]->isBitField())6756 RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result);6757 else6758 WriteInternalIvarName(CDecl, IvarDecl, Result);6759 Result += ", ";6760 6761 Result += "\"";6762 if (Ivars[i]->isBitField())6763 RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result);6764 else6765 Result += IvarDecl->getName();6766 Result += "\", ";6767 6768 QualType IVQT = IvarDecl->getType();6769 if (IvarDecl->isBitField())6770 IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl);6771 6772 std::string IvarTypeString, QuoteIvarTypeString;6773 Context->getObjCEncodingForType(IVQT, IvarTypeString,6774 IvarDecl);6775 RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString);6776 Result += "\""; Result += QuoteIvarTypeString; Result += "\", ";6777 6778 // FIXME. this alignment represents the host alignment and need be changed to6779 // represent the target alignment.6780 unsigned Align = Context->getTypeAlign(IVQT)/8;6781 Align = llvm::Log2_32(Align);6782 Result += llvm::utostr(Align); Result += ", ";6783 CharUnits Size = Context->getTypeSizeInChars(IVQT);6784 Result += llvm::utostr(Size.getQuantity());6785 if (i == e-1)6786 Result += "}}\n";6787 else6788 Result += "},\n";6789 }6790 Result += "};\n";6791 }6792}6793 6794/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data.6795void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl,6796 std::string &Result) {6797 6798 // Do not synthesize the protocol more than once.6799 if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl()))6800 return;6801 WriteModernMetadataDeclarations(Context, Result);6802 6803 if (ObjCProtocolDecl *Def = PDecl->getDefinition())6804 PDecl = Def;6805 // Must write out all protocol definitions in current qualifier list,6806 // and in their nested qualifiers before writing out current definition.6807 for (auto *I : PDecl->protocols())6808 RewriteObjCProtocolMetaData(I, Result);6809 6810 // Construct method lists.6811 std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods;6812 std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods;6813 for (auto *MD : PDecl->instance_methods()) {6814 if (MD->getImplementationControl() == ObjCImplementationControl::Optional) {6815 OptInstanceMethods.push_back(MD);6816 } else {6817 InstanceMethods.push_back(MD);6818 }6819 }6820 6821 for (auto *MD : PDecl->class_methods()) {6822 if (MD->getImplementationControl() == ObjCImplementationControl::Optional) {6823 OptClassMethods.push_back(MD);6824 } else {6825 ClassMethods.push_back(MD);6826 }6827 }6828 std::vector<ObjCMethodDecl *> AllMethods;6829 for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++)6830 AllMethods.push_back(InstanceMethods[i]);6831 for (unsigned i = 0, e = ClassMethods.size(); i < e; i++)6832 AllMethods.push_back(ClassMethods[i]);6833 for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++)6834 AllMethods.push_back(OptInstanceMethods[i]);6835 for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++)6836 AllMethods.push_back(OptClassMethods[i]);6837 6838 Write__extendedMethodTypes_initializer(*this, Context, Result,6839 AllMethods,6840 "_OBJC_PROTOCOL_METHOD_TYPES_",6841 PDecl->getNameAsString());6842 // Protocol's super protocol list6843 SmallVector<ObjCProtocolDecl *, 8> SuperProtocols(PDecl->protocols());6844 Write_protocol_list_initializer(Context, Result, SuperProtocols,6845 "_OBJC_PROTOCOL_REFS_",6846 PDecl->getNameAsString());6847 6848 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,6849 "_OBJC_PROTOCOL_INSTANCE_METHODS_",6850 PDecl->getNameAsString(), false);6851 6852 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,6853 "_OBJC_PROTOCOL_CLASS_METHODS_",6854 PDecl->getNameAsString(), false);6855 6856 Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods,6857 "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_",6858 PDecl->getNameAsString(), false);6859 6860 Write_method_list_t_initializer(*this, Context, Result, OptClassMethods,6861 "_OBJC_PROTOCOL_OPT_CLASS_METHODS_",6862 PDecl->getNameAsString(), false);6863 6864 // Protocol's property metadata.6865 SmallVector<ObjCPropertyDecl *, 8> ProtocolProperties(6866 PDecl->instance_properties());6867 Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties,6868 /* Container */nullptr,6869 "_OBJC_PROTOCOL_PROPERTIES_",6870 PDecl->getNameAsString());6871 6872 // Writer out root metadata for current protocol: struct _protocol_t6873 Result += "\n";6874 if (LangOpts.MicrosoftExt)6875 Result += "static ";6876 Result += "struct _protocol_t _OBJC_PROTOCOL_";6877 Result += PDecl->getNameAsString();6878 Result += " __attribute__ ((used)) = {\n";6879 Result += "\t0,\n"; // id is; is null6880 Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n";6881 if (SuperProtocols.size() > 0) {6882 Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_";6883 Result += PDecl->getNameAsString(); Result += ",\n";6884 }6885 else6886 Result += "\t0,\n";6887 if (InstanceMethods.size() > 0) {6888 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_";6889 Result += PDecl->getNameAsString(); Result += ",\n";6890 }6891 else6892 Result += "\t0,\n";6893 6894 if (ClassMethods.size() > 0) {6895 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_";6896 Result += PDecl->getNameAsString(); Result += ",\n";6897 }6898 else6899 Result += "\t0,\n";6900 6901 if (OptInstanceMethods.size() > 0) {6902 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_";6903 Result += PDecl->getNameAsString(); Result += ",\n";6904 }6905 else6906 Result += "\t0,\n";6907 6908 if (OptClassMethods.size() > 0) {6909 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_";6910 Result += PDecl->getNameAsString(); Result += ",\n";6911 }6912 else6913 Result += "\t0,\n";6914 6915 if (ProtocolProperties.size() > 0) {6916 Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_";6917 Result += PDecl->getNameAsString(); Result += ",\n";6918 }6919 else6920 Result += "\t0,\n";6921 6922 Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n";6923 Result += "\t0,\n";6924 6925 if (AllMethods.size() > 0) {6926 Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_";6927 Result += PDecl->getNameAsString();6928 Result += "\n};\n";6929 }6930 else6931 Result += "\t0\n};\n";6932 6933 if (LangOpts.MicrosoftExt)6934 Result += "static ";6935 Result += "struct _protocol_t *";6936 Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString();6937 Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString();6938 Result += ";\n";6939 6940 // Mark this protocol as having been generated.6941 if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl()).second)6942 llvm_unreachable("protocol already synthesized");6943}6944 6945/// hasObjCExceptionAttribute - Return true if this class or any super6946/// class has the __objc_exception__ attribute.6947/// FIXME. Move this to ASTContext.cpp as it is also used for IRGen.6948static bool hasObjCExceptionAttribute(ASTContext &Context,6949 const ObjCInterfaceDecl *OID) {6950 if (OID->hasAttr<ObjCExceptionAttr>())6951 return true;6952 if (const ObjCInterfaceDecl *Super = OID->getSuperClass())6953 return hasObjCExceptionAttribute(Context, Super);6954 return false;6955}6956 6957void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,6958 std::string &Result) {6959 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();6960 6961 // Explicitly declared @interface's are already synthesized.6962 if (CDecl->isImplicitInterfaceDecl())6963 assert(false &&6964 "Legacy implicit interface rewriting not supported in moder abi");6965 6966 WriteModernMetadataDeclarations(Context, Result);6967 SmallVector<ObjCIvarDecl *, 8> IVars;6968 6969 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();6970 IVD; IVD = IVD->getNextIvar()) {6971 // Ignore unnamed bit-fields.6972 if (!IVD->getDeclName())6973 continue;6974 IVars.push_back(IVD);6975 }6976 6977 Write__ivar_list_t_initializer(*this, Context, Result, IVars,6978 "_OBJC_$_INSTANCE_VARIABLES_",6979 CDecl);6980 6981 // Build _objc_method_list for class's instance methods if needed6982 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());6983 6984 // If any of our property implementations have associated getters or6985 // setters, produce metadata for them as well.6986 for (const auto *Prop : IDecl->property_impls()) {6987 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)6988 continue;6989 if (!Prop->getPropertyIvarDecl())6990 continue;6991 ObjCPropertyDecl *PD = Prop->getPropertyDecl();6992 if (!PD)6993 continue;6994 if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())6995 if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/))6996 InstanceMethods.push_back(Getter);6997 if (PD->isReadOnly())6998 continue;6999 if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())7000 if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/))7001 InstanceMethods.push_back(Setter);7002 }7003 7004 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,7005 "_OBJC_$_INSTANCE_METHODS_",7006 IDecl->getNameAsString(), true);7007 7008 SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());7009 7010 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,7011 "_OBJC_$_CLASS_METHODS_",7012 IDecl->getNameAsString(), true);7013 7014 // Protocols referenced in class declaration?7015 // Protocol's super protocol list7016 std::vector<ObjCProtocolDecl *> RefedProtocols;7017 const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols();7018 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),7019 E = Protocols.end();7020 I != E; ++I) {7021 RefedProtocols.push_back(*I);7022 // Must write out all protocol definitions in current qualifier list,7023 // and in their nested qualifiers before writing out current definition.7024 RewriteObjCProtocolMetaData(*I, Result);7025 }7026 7027 Write_protocol_list_initializer(Context, Result,7028 RefedProtocols,7029 "_OBJC_CLASS_PROTOCOLS_$_",7030 IDecl->getNameAsString());7031 7032 // Protocol's property metadata.7033 SmallVector<ObjCPropertyDecl *, 8> ClassProperties(7034 CDecl->instance_properties());7035 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,7036 /* Container */IDecl,7037 "_OBJC_$_PROP_LIST_",7038 CDecl->getNameAsString());7039 7040 // Data for initializing _class_ro_t metaclass meta-data7041 uint32_t flags = CLS_META;7042 std::string InstanceSize;7043 std::string InstanceStart;7044 7045 bool classIsHidden = CDecl->getVisibility() == HiddenVisibility;7046 if (classIsHidden)7047 flags |= OBJC2_CLS_HIDDEN;7048 7049 if (!CDecl->getSuperClass())7050 // class is root7051 flags |= CLS_ROOT;7052 InstanceSize = "sizeof(struct _class_t)";7053 InstanceStart = InstanceSize;7054 Write__class_ro_t_initializer(Context, Result, flags,7055 InstanceStart, InstanceSize,7056 ClassMethods,7057 nullptr,7058 nullptr,7059 nullptr,7060 "_OBJC_METACLASS_RO_$_",7061 CDecl->getNameAsString());7062 7063 // Data for initializing _class_ro_t meta-data7064 flags = CLS;7065 if (classIsHidden)7066 flags |= OBJC2_CLS_HIDDEN;7067 7068 if (hasObjCExceptionAttribute(*Context, CDecl))7069 flags |= CLS_EXCEPTION;7070 7071 if (!CDecl->getSuperClass())7072 // class is root7073 flags |= CLS_ROOT;7074 7075 InstanceSize.clear();7076 InstanceStart.clear();7077 if (!ObjCSynthesizedStructs.count(CDecl)) {7078 InstanceSize = "0";7079 InstanceStart = "0";7080 }7081 else {7082 InstanceSize = "sizeof(struct ";7083 InstanceSize += CDecl->getNameAsString();7084 InstanceSize += "_IMPL)";7085 7086 ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin();7087 if (IVD) {7088 RewriteIvarOffsetComputation(IVD, InstanceStart);7089 }7090 else7091 InstanceStart = InstanceSize;7092 }7093 Write__class_ro_t_initializer(Context, Result, flags,7094 InstanceStart, InstanceSize,7095 InstanceMethods,7096 RefedProtocols,7097 IVars,7098 ClassProperties,7099 "_OBJC_CLASS_RO_$_",7100 CDecl->getNameAsString());7101 7102 Write_class_t(Context, Result,7103 "OBJC_METACLASS_$_",7104 CDecl, /*metaclass*/true);7105 7106 Write_class_t(Context, Result,7107 "OBJC_CLASS_$_",7108 CDecl, /*metaclass*/false);7109 7110 if (ImplementationIsNonLazy(IDecl))7111 DefinedNonLazyClasses.push_back(CDecl);7112}7113 7114void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) {7115 int ClsDefCount = ClassImplementation.size();7116 if (!ClsDefCount)7117 return;7118 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";7119 Result += "__declspec(allocate(\".objc_inithooks$B\")) ";7120 Result += "static void *OBJC_CLASS_SETUP[] = {\n";7121 for (int i = 0; i < ClsDefCount; i++) {7122 ObjCImplementationDecl *IDecl = ClassImplementation[i];7123 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface();7124 Result += "\t(void *)&OBJC_CLASS_SETUP_$_";7125 Result += CDecl->getName(); Result += ",\n";7126 }7127 Result += "};\n";7128}7129 7130void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) {7131 int ClsDefCount = ClassImplementation.size();7132 int CatDefCount = CategoryImplementation.size();7133 7134 // For each implemented class, write out all its meta data.7135 for (int i = 0; i < ClsDefCount; i++)7136 RewriteObjCClassMetaData(ClassImplementation[i], Result);7137 7138 RewriteClassSetupInitHook(Result);7139 7140 // For each implemented category, write out all its meta data.7141 for (int i = 0; i < CatDefCount; i++)7142 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result);7143 7144 RewriteCategorySetupInitHook(Result);7145 7146 if (ClsDefCount > 0) {7147 if (LangOpts.MicrosoftExt)7148 Result += "__declspec(allocate(\".objc_classlist$B\")) ";7149 Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ [";7150 Result += llvm::utostr(ClsDefCount); Result += "]";7151 Result +=7152 " __attribute__((used, section (\"__DATA, __objc_classlist,"7153 "regular,no_dead_strip\")))= {\n";7154 for (int i = 0; i < ClsDefCount; i++) {7155 Result += "\t&OBJC_CLASS_$_";7156 Result += ClassImplementation[i]->getNameAsString();7157 Result += ",\n";7158 }7159 Result += "};\n";7160 7161 if (!DefinedNonLazyClasses.empty()) {7162 if (LangOpts.MicrosoftExt)7163 Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n";7164 Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t";7165 for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) {7166 Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString();7167 Result += ",\n";7168 }7169 Result += "};\n";7170 }7171 }7172 7173 if (CatDefCount > 0) {7174 if (LangOpts.MicrosoftExt)7175 Result += "__declspec(allocate(\".objc_catlist$B\")) ";7176 Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [";7177 Result += llvm::utostr(CatDefCount); Result += "]";7178 Result +=7179 " __attribute__((used, section (\"__DATA, __objc_catlist,"7180 "regular,no_dead_strip\")))= {\n";7181 for (int i = 0; i < CatDefCount; i++) {7182 Result += "\t&_OBJC_$_CATEGORY_";7183 Result +=7184 CategoryImplementation[i]->getClassInterface()->getNameAsString();7185 Result += "_$_";7186 Result += CategoryImplementation[i]->getNameAsString();7187 Result += ",\n";7188 }7189 Result += "};\n";7190 }7191 7192 if (!DefinedNonLazyCategories.empty()) {7193 if (LangOpts.MicrosoftExt)7194 Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n";7195 Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t";7196 for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) {7197 Result += "\t&_OBJC_$_CATEGORY_";7198 Result +=7199 DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString();7200 Result += "_$_";7201 Result += DefinedNonLazyCategories[i]->getNameAsString();7202 Result += ",\n";7203 }7204 Result += "};\n";7205 }7206}7207 7208void RewriteModernObjC::WriteImageInfo(std::string &Result) {7209 if (LangOpts.MicrosoftExt)7210 Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n";7211 7212 Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } ";7213 // version 0, ObjCABI is 27214 Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n";7215}7216 7217/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category7218/// implementation.7219void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl,7220 std::string &Result) {7221 WriteModernMetadataDeclarations(Context, Result);7222 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();7223 // Find category declaration for this implementation.7224 ObjCCategoryDecl *CDecl7225 = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier());7226 7227 std::string FullCategoryName = ClassDecl->getNameAsString();7228 FullCategoryName += "_$_";7229 FullCategoryName += CDecl->getNameAsString();7230 7231 // Build _objc_method_list for class's instance methods if needed7232 SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instance_methods());7233 7234 // If any of our property implementations have associated getters or7235 // setters, produce metadata for them as well.7236 for (const auto *Prop : IDecl->property_impls()) {7237 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)7238 continue;7239 if (!Prop->getPropertyIvarDecl())7240 continue;7241 ObjCPropertyDecl *PD = Prop->getPropertyDecl();7242 if (!PD)7243 continue;7244 if (ObjCMethodDecl *Getter = Prop->getGetterMethodDecl())7245 InstanceMethods.push_back(Getter);7246 if (PD->isReadOnly())7247 continue;7248 if (ObjCMethodDecl *Setter = Prop->getSetterMethodDecl())7249 InstanceMethods.push_back(Setter);7250 }7251 7252 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods,7253 "_OBJC_$_CATEGORY_INSTANCE_METHODS_",7254 FullCategoryName, true);7255 7256 SmallVector<ObjCMethodDecl *, 32> ClassMethods(IDecl->class_methods());7257 7258 Write_method_list_t_initializer(*this, Context, Result, ClassMethods,7259 "_OBJC_$_CATEGORY_CLASS_METHODS_",7260 FullCategoryName, true);7261 7262 // Protocols referenced in class declaration?7263 // Protocol's super protocol list7264 SmallVector<ObjCProtocolDecl *, 8> RefedProtocols(CDecl->protocols());7265 for (auto *I : CDecl->protocols())7266 // Must write out all protocol definitions in current qualifier list,7267 // and in their nested qualifiers before writing out current definition.7268 RewriteObjCProtocolMetaData(I, Result);7269 7270 Write_protocol_list_initializer(Context, Result,7271 RefedProtocols,7272 "_OBJC_CATEGORY_PROTOCOLS_$_",7273 FullCategoryName);7274 7275 // Protocol's property metadata.7276 SmallVector<ObjCPropertyDecl *, 8> ClassProperties(7277 CDecl->instance_properties());7278 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties,7279 /* Container */IDecl,7280 "_OBJC_$_PROP_LIST_",7281 FullCategoryName);7282 7283 Write_category_t(*this, Context, Result,7284 CDecl,7285 ClassDecl,7286 InstanceMethods,7287 ClassMethods,7288 RefedProtocols,7289 ClassProperties);7290 7291 // Determine if this category is also "non-lazy".7292 if (ImplementationIsNonLazy(IDecl))7293 DefinedNonLazyCategories.push_back(CDecl);7294}7295 7296void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) {7297 int CatDefCount = CategoryImplementation.size();7298 if (!CatDefCount)7299 return;7300 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n";7301 Result += "__declspec(allocate(\".objc_inithooks$B\")) ";7302 Result += "static void *OBJC_CATEGORY_SETUP[] = {\n";7303 for (int i = 0; i < CatDefCount; i++) {7304 ObjCCategoryImplDecl *IDecl = CategoryImplementation[i];7305 ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl();7306 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface();7307 Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_";7308 Result += ClassDecl->getName();7309 Result += "_$_";7310 Result += CatDecl->getName();7311 Result += ",\n";7312 }7313 Result += "};\n";7314}7315 7316// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or7317/// class methods.7318template<typename MethodIterator>7319void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,7320 MethodIterator MethodEnd,7321 bool IsInstanceMethod,7322 StringRef prefix,7323 StringRef ClassName,7324 std::string &Result) {7325 if (MethodBegin == MethodEnd) return;7326 7327 if (!objc_impl_method) {7328 /* struct _objc_method {7329 SEL _cmd;7330 char *method_types;7331 void *_imp;7332 }7333 */7334 Result += "\nstruct _objc_method {\n";7335 Result += "\tSEL _cmd;\n";7336 Result += "\tchar *method_types;\n";7337 Result += "\tvoid *_imp;\n";7338 Result += "};\n";7339 7340 objc_impl_method = true;7341 }7342 7343 // Build _objc_method_list for class's methods if needed7344 7345 /* struct {7346 struct _objc_method_list *next_method;7347 int method_count;7348 struct _objc_method method_list[];7349 }7350 */7351 unsigned NumMethods = std::distance(MethodBegin, MethodEnd);7352 Result += "\n";7353 if (LangOpts.MicrosoftExt) {7354 if (IsInstanceMethod)7355 Result += "__declspec(allocate(\".inst_meth$B\")) ";7356 else7357 Result += "__declspec(allocate(\".cls_meth$B\")) ";7358 }7359 Result += "static struct {\n";7360 Result += "\tstruct _objc_method_list *next_method;\n";7361 Result += "\tint method_count;\n";7362 Result += "\tstruct _objc_method method_list[";7363 Result += utostr(NumMethods);7364 Result += "];\n} _OBJC_";7365 Result += prefix;7366 Result += IsInstanceMethod ? "INSTANCE" : "CLASS";7367 Result += "_METHODS_";7368 Result += ClassName;7369 Result += " __attribute__ ((used, section (\"__OBJC, __";7370 Result += IsInstanceMethod ? "inst" : "cls";7371 Result += "_meth\")))= ";7372 Result += "{\n\t0, " + utostr(NumMethods) + "\n";7373 7374 Result += "\t,{{(SEL)\"";7375 Result += (*MethodBegin)->getSelector().getAsString().c_str();7376 std::string MethodTypeString;7377 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);7378 Result += "\", \"";7379 Result += MethodTypeString;7380 Result += "\", (void *)";7381 Result += MethodInternalNames[*MethodBegin];7382 Result += "}\n";7383 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) {7384 Result += "\t ,{(SEL)\"";7385 Result += (*MethodBegin)->getSelector().getAsString().c_str();7386 std::string MethodTypeString;7387 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString);7388 Result += "\", \"";7389 Result += MethodTypeString;7390 Result += "\", (void *)";7391 Result += MethodInternalNames[*MethodBegin];7392 Result += "}\n";7393 }7394 Result += "\t }\n};\n";7395}7396 7397Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) {7398 SourceRange OldRange = IV->getSourceRange();7399 Expr *BaseExpr = IV->getBase();7400 7401 // Rewrite the base, but without actually doing replaces.7402 {7403 DisableReplaceStmtScope S(*this);7404 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr));7405 IV->setBase(BaseExpr);7406 }7407 7408 ObjCIvarDecl *D = IV->getDecl();7409 7410 Expr *Replacement = IV;7411 7412 if (BaseExpr->getType()->isObjCObjectPointerType()) {7413 const ObjCInterfaceType *iFaceDecl =7414 dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());7415 assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");7416 // lookup which class implements the instance variable.7417 ObjCInterfaceDecl *clsDeclared = nullptr;7418 iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),7419 clsDeclared);7420 assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");7421 7422 // Build name of symbol holding ivar offset.7423 std::string IvarOffsetName;7424 if (D->isBitField())7425 ObjCIvarBitfieldGroupOffset(D, IvarOffsetName);7426 else7427 WriteInternalIvarName(clsDeclared, D, IvarOffsetName);7428 7429 ReferencedIvars[clsDeclared].insert(D);7430 7431 // cast offset to "char *".7432 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context,7433 Context->getPointerType(Context->CharTy),7434 CK_BitCast,7435 BaseExpr);7436 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),7437 SourceLocation(), &Context->Idents.get(IvarOffsetName),7438 Context->UnsignedLongTy, nullptr,7439 SC_Extern);7440 DeclRefExpr *DRE = new (Context)7441 DeclRefExpr(*Context, NewVD, false, Context->UnsignedLongTy,7442 VK_LValue, SourceLocation());7443 BinaryOperator *addExpr = BinaryOperator::Create(7444 *Context, castExpr, DRE, BO_Add,7445 Context->getPointerType(Context->CharTy), VK_PRValue, OK_Ordinary,7446 SourceLocation(), FPOptionsOverride());7447 // Don't forget the parens to enforce the proper binding.7448 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(),7449 SourceLocation(),7450 addExpr);7451 QualType IvarT = D->getType();7452 if (D->isBitField())7453 IvarT = GetGroupRecordTypeForObjCIvarBitfield(D);7454 7455 if (!IvarT->getAs<TypedefType>() && IvarT->isRecordType()) {7456 RecordDecl *RD = IvarT->castAsCanonical<RecordType>()->getDecl();7457 RD = RD->getDefinition();7458 if (RD && !RD->getDeclName().getAsIdentifierInfo()) {7459 // decltype(((Foo_IMPL*)0)->bar) *7460 auto *CDecl = cast<ObjCContainerDecl>(D->getDeclContext());7461 // ivar in class extensions requires special treatment.7462 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl))7463 CDecl = CatDecl->getClassInterface();7464 std::string RecName = std::string(CDecl->getName());7465 RecName += "_IMPL";7466 RecordDecl *RD = RecordDecl::Create(7467 *Context, TagTypeKind::Struct, TUDecl, SourceLocation(),7468 SourceLocation(), &Context->Idents.get(RecName));7469 QualType PtrStructIMPL =7470 Context->getPointerType(Context->getCanonicalTagType(RD));7471 unsigned UnsignedIntSize =7472 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy));7473 Expr *Zero = IntegerLiteral::Create(*Context,7474 llvm::APInt(UnsignedIntSize, 0),7475 Context->UnsignedIntTy, SourceLocation());7476 Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero);7477 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),7478 Zero);7479 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),7480 SourceLocation(),7481 &Context->Idents.get(D->getNameAsString()),7482 IvarT, nullptr,7483 /*BitWidth=*/nullptr,7484 /*Mutable=*/true, ICIS_NoInit);7485 MemberExpr *ME = MemberExpr::CreateImplicit(7486 *Context, PE, true, FD, FD->getType(), VK_LValue, OK_Ordinary);7487 IvarT = Context->getDecltypeType(ME, ME->getType());7488 }7489 }7490 convertObjCTypeToCStyleType(IvarT);7491 QualType castT = Context->getPointerType(IvarT);7492 7493 castExpr = NoTypeInfoCStyleCastExpr(Context,7494 castT,7495 CK_BitCast,7496 PE);7497 7498 Expr *Exp = UnaryOperator::Create(7499 const_cast<ASTContext &>(*Context), castExpr, UO_Deref, IvarT,7500 VK_LValue, OK_Ordinary, SourceLocation(), false, FPOptionsOverride());7501 PE = new (Context) ParenExpr(OldRange.getBegin(),7502 OldRange.getEnd(),7503 Exp);7504 7505 if (D->isBitField()) {7506 FieldDecl *FD = FieldDecl::Create(*Context, nullptr, SourceLocation(),7507 SourceLocation(),7508 &Context->Idents.get(D->getNameAsString()),7509 D->getType(), nullptr,7510 /*BitWidth=*/D->getBitWidth(),7511 /*Mutable=*/true, ICIS_NoInit);7512 MemberExpr *ME =7513 MemberExpr::CreateImplicit(*Context, PE, /*isArrow*/ false, FD,7514 FD->getType(), VK_LValue, OK_Ordinary);7515 Replacement = ME;7516 7517 }7518 else7519 Replacement = PE;7520 }7521 7522 ReplaceStmtWithRange(IV, Replacement, OldRange);7523 return Replacement;7524}7525 7526#endif // CLANG_ENABLE_OBJC_REWRITER7527