1243791Sdim//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===// 2243791Sdim// 3243791Sdim// The LLVM Compiler Infrastructure 4243791Sdim// 5243791Sdim// This file is distributed under the University of Illinois Open Source 6243791Sdim// License. See LICENSE.TXT for details. 7243791Sdim// 8243791Sdim//===----------------------------------------------------------------------===// 9243791Sdim// 10243791Sdim// Hacks and fun related to the code rewriter. 11243791Sdim// 12243791Sdim//===----------------------------------------------------------------------===// 13243791Sdim 14243791Sdim#include "clang/Rewrite/Frontend/ASTConsumers.h" 15243791Sdim#include "clang/AST/AST.h" 16243791Sdim#include "clang/AST/ASTConsumer.h" 17249423Sdim#include "clang/AST/Attr.h" 18243791Sdim#include "clang/AST/ParentMap.h" 19249423Sdim#include "clang/Basic/CharInfo.h" 20249423Sdim#include "clang/Basic/Diagnostic.h" 21249423Sdim#include "clang/Basic/IdentifierTable.h" 22243791Sdim#include "clang/Basic/SourceManager.h" 23249423Sdim#include "clang/Basic/TargetInfo.h" 24243791Sdim#include "clang/Lex/Lexer.h" 25249423Sdim#include "clang/Rewrite/Core/Rewriter.h" 26249423Sdim#include "llvm/ADT/DenseSet.h" 27249423Sdim#include "llvm/ADT/OwningPtr.h" 28249423Sdim#include "llvm/ADT/SmallPtrSet.h" 29249423Sdim#include "llvm/ADT/StringExtras.h" 30243791Sdim#include "llvm/Support/MemoryBuffer.h" 31243791Sdim#include "llvm/Support/raw_ostream.h" 32243791Sdim 33243791Sdimusing namespace clang; 34243791Sdimusing llvm::utostr; 35243791Sdim 36243791Sdimnamespace { 37243791Sdim class RewriteModernObjC : public ASTConsumer { 38243791Sdim protected: 39243791Sdim 40243791Sdim enum { 41243791Sdim BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 42243791Sdim block, ... */ 43243791Sdim BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 44243791Sdim BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the 45243791Sdim __block variable */ 46243791Sdim BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 47243791Sdim helpers */ 48243791Sdim BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 49243791Sdim support routines */ 50243791Sdim BLOCK_BYREF_CURRENT_MAX = 256 51243791Sdim }; 52243791Sdim 53243791Sdim enum { 54243791Sdim BLOCK_NEEDS_FREE = (1 << 24), 55243791Sdim BLOCK_HAS_COPY_DISPOSE = (1 << 25), 56243791Sdim BLOCK_HAS_CXX_OBJ = (1 << 26), 57243791Sdim BLOCK_IS_GC = (1 << 27), 58243791Sdim BLOCK_IS_GLOBAL = (1 << 28), 59243791Sdim BLOCK_HAS_DESCRIPTOR = (1 << 29) 60243791Sdim }; 61243791Sdim 62243791Sdim Rewriter Rewrite; 63243791Sdim DiagnosticsEngine &Diags; 64243791Sdim const LangOptions &LangOpts; 65243791Sdim ASTContext *Context; 66243791Sdim SourceManager *SM; 67243791Sdim TranslationUnitDecl *TUDecl; 68243791Sdim FileID MainFileID; 69243791Sdim const char *MainFileStart, *MainFileEnd; 70243791Sdim Stmt *CurrentBody; 71243791Sdim ParentMap *PropParentMap; // created lazily. 72243791Sdim std::string InFileName; 73243791Sdim raw_ostream* OutFile; 74243791Sdim std::string Preamble; 75243791Sdim 76243791Sdim TypeDecl *ProtocolTypeDecl; 77243791Sdim VarDecl *GlobalVarDecl; 78243791Sdim Expr *GlobalConstructionExp; 79243791Sdim unsigned RewriteFailedDiag; 80243791Sdim unsigned GlobalBlockRewriteFailedDiag; 81243791Sdim // ObjC string constant support. 82243791Sdim unsigned NumObjCStringLiterals; 83243791Sdim VarDecl *ConstantStringClassReference; 84243791Sdim RecordDecl *NSStringRecord; 85243791Sdim 86243791Sdim // ObjC foreach break/continue generation support. 87243791Sdim int BcLabelCount; 88243791Sdim 89243791Sdim unsigned TryFinallyContainsReturnDiag; 90243791Sdim // Needed for super. 91243791Sdim ObjCMethodDecl *CurMethodDef; 92243791Sdim RecordDecl *SuperStructDecl; 93243791Sdim RecordDecl *ConstantStringDecl; 94243791Sdim 95243791Sdim FunctionDecl *MsgSendFunctionDecl; 96243791Sdim FunctionDecl *MsgSendSuperFunctionDecl; 97243791Sdim FunctionDecl *MsgSendStretFunctionDecl; 98243791Sdim FunctionDecl *MsgSendSuperStretFunctionDecl; 99243791Sdim FunctionDecl *MsgSendFpretFunctionDecl; 100243791Sdim FunctionDecl *GetClassFunctionDecl; 101243791Sdim FunctionDecl *GetMetaClassFunctionDecl; 102243791Sdim FunctionDecl *GetSuperClassFunctionDecl; 103243791Sdim FunctionDecl *SelGetUidFunctionDecl; 104243791Sdim FunctionDecl *CFStringFunctionDecl; 105263508Sdim FunctionDecl *SuperConstructorFunctionDecl; 106243791Sdim FunctionDecl *CurFunctionDef; 107243791Sdim 108243791Sdim /* Misc. containers needed for meta-data rewrite. */ 109243791Sdim SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; 110243791Sdim SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; 111243791Sdim llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; 112243791Sdim llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; 113243791Sdim llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces; 114243791Sdim llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags; 115243791Sdim SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen; 116243791Sdim /// DefinedNonLazyClasses - List of defined "non-lazy" classes. 117243791Sdim SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses; 118243791Sdim 119243791Sdim /// DefinedNonLazyCategories - List of defined "non-lazy" categories. 120249423Sdim SmallVector<ObjCCategoryDecl *, 8> DefinedNonLazyCategories; 121243791Sdim 122243791Sdim SmallVector<Stmt *, 32> Stmts; 123243791Sdim SmallVector<int, 8> ObjCBcLabelNo; 124243791Sdim // Remember all the @protocol(<expr>) expressions. 125243791Sdim llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; 126243791Sdim 127243791Sdim llvm::DenseSet<uint64_t> CopyDestroyCache; 128243791Sdim 129243791Sdim // Block expressions. 130243791Sdim SmallVector<BlockExpr *, 32> Blocks; 131243791Sdim SmallVector<int, 32> InnerDeclRefsCount; 132243791Sdim SmallVector<DeclRefExpr *, 32> InnerDeclRefs; 133243791Sdim 134243791Sdim SmallVector<DeclRefExpr *, 32> BlockDeclRefs; 135243791Sdim 136249423Sdim 137243791Sdim // Block related declarations. 138243791Sdim SmallVector<ValueDecl *, 8> BlockByCopyDecls; 139243791Sdim llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; 140243791Sdim SmallVector<ValueDecl *, 8> BlockByRefDecls; 141243791Sdim llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; 142243791Sdim llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; 143243791Sdim llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; 144243791Sdim llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls; 145243791Sdim 146243791Sdim llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; 147243791Sdim llvm::DenseMap<ObjCInterfaceDecl *, 148243791Sdim llvm::SmallPtrSet<ObjCIvarDecl *, 8> > ReferencedIvars; 149243791Sdim 150249423Sdim // ivar bitfield grouping containers 151249423Sdim llvm::DenseSet<const ObjCInterfaceDecl *> ObjCInterefaceHasBitfieldGroups; 152249423Sdim llvm::DenseMap<const ObjCIvarDecl* , unsigned> IvarGroupNumber; 153249423Sdim // This container maps an <class, group number for ivar> tuple to the type 154249423Sdim // of the struct where the bitfield belongs. 155249423Sdim llvm::DenseMap<std::pair<const ObjCInterfaceDecl*, unsigned>, QualType> GroupRecordType; 156249423Sdim SmallVector<FunctionDecl*, 32> FunctionDefinitionsSeen; 157249423Sdim 158243791Sdim // This maps an original source AST to it's rewritten form. This allows 159243791Sdim // us to avoid rewriting the same node twice (which is very uncommon). 160243791Sdim // This is needed to support some of the exotic property rewriting. 161243791Sdim llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; 162243791Sdim 163243791Sdim // Needed for header files being rewritten 164243791Sdim bool IsHeader; 165243791Sdim bool SilenceRewriteMacroWarning; 166249423Sdim bool GenerateLineInfo; 167243791Sdim bool objc_impl_method; 168243791Sdim 169243791Sdim bool DisableReplaceStmt; 170243791Sdim class DisableReplaceStmtScope { 171243791Sdim RewriteModernObjC &R; 172243791Sdim bool SavedValue; 173243791Sdim 174243791Sdim public: 175243791Sdim DisableReplaceStmtScope(RewriteModernObjC &R) 176243791Sdim : R(R), SavedValue(R.DisableReplaceStmt) { 177243791Sdim R.DisableReplaceStmt = true; 178243791Sdim } 179243791Sdim ~DisableReplaceStmtScope() { 180243791Sdim R.DisableReplaceStmt = SavedValue; 181243791Sdim } 182243791Sdim }; 183243791Sdim void InitializeCommon(ASTContext &context); 184243791Sdim 185243791Sdim public: 186243791Sdim llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; 187243791Sdim // Top Level Driver code. 188243791Sdim virtual bool HandleTopLevelDecl(DeclGroupRef D) { 189243791Sdim for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 190243791Sdim if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) { 191243791Sdim if (!Class->isThisDeclarationADefinition()) { 192243791Sdim RewriteForwardClassDecl(D); 193243791Sdim break; 194243791Sdim } else { 195243791Sdim // Keep track of all interface declarations seen. 196243791Sdim ObjCInterfacesSeen.push_back(Class); 197243791Sdim break; 198243791Sdim } 199243791Sdim } 200243791Sdim 201243791Sdim if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) { 202243791Sdim if (!Proto->isThisDeclarationADefinition()) { 203243791Sdim RewriteForwardProtocolDecl(D); 204243791Sdim break; 205243791Sdim } 206243791Sdim } 207243791Sdim 208249423Sdim if (FunctionDecl *FDecl = dyn_cast<FunctionDecl>(*I)) { 209249423Sdim // Under modern abi, we cannot translate body of the function 210249423Sdim // yet until all class extensions and its implementation is seen. 211249423Sdim // This is because they may introduce new bitfields which must go 212249423Sdim // into their grouping struct. 213249423Sdim if (FDecl->isThisDeclarationADefinition() && 214249423Sdim // Not c functions defined inside an objc container. 215249423Sdim !FDecl->isTopLevelDeclInObjCContainer()) { 216249423Sdim FunctionDefinitionsSeen.push_back(FDecl); 217249423Sdim break; 218249423Sdim } 219249423Sdim } 220243791Sdim HandleTopLevelSingleDecl(*I); 221243791Sdim } 222243791Sdim return true; 223243791Sdim } 224263508Sdim 225263508Sdim virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) { 226263508Sdim for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 227263508Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(*I)) { 228263508Sdim if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 229263508Sdim RewriteBlockPointerDecl(TD); 230263508Sdim else if (TD->getUnderlyingType()->isFunctionPointerType()) 231263508Sdim CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 232263508Sdim else 233263508Sdim RewriteObjCQualifiedInterfaceTypes(TD); 234263508Sdim } 235263508Sdim } 236263508Sdim return; 237263508Sdim } 238263508Sdim 239243791Sdim void HandleTopLevelSingleDecl(Decl *D); 240243791Sdim void HandleDeclInMainFile(Decl *D); 241243791Sdim RewriteModernObjC(std::string inFile, raw_ostream *OS, 242243791Sdim DiagnosticsEngine &D, const LangOptions &LOpts, 243249423Sdim bool silenceMacroWarn, bool LineInfo); 244243791Sdim 245243791Sdim ~RewriteModernObjC() {} 246243791Sdim 247243791Sdim virtual void HandleTranslationUnit(ASTContext &C); 248243791Sdim 249243791Sdim void ReplaceStmt(Stmt *Old, Stmt *New) { 250243791Sdim Stmt *ReplacingStmt = ReplacedNodes[Old]; 251243791Sdim 252243791Sdim if (ReplacingStmt) 253243791Sdim return; // We can't rewrite the same node twice. 254243791Sdim 255243791Sdim if (DisableReplaceStmt) 256243791Sdim return; 257243791Sdim 258243791Sdim // If replacement succeeded or warning disabled return with no warning. 259243791Sdim if (!Rewrite.ReplaceStmt(Old, New)) { 260243791Sdim ReplacedNodes[Old] = New; 261243791Sdim return; 262243791Sdim } 263243791Sdim if (SilenceRewriteMacroWarning) 264243791Sdim return; 265243791Sdim Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 266243791Sdim << Old->getSourceRange(); 267243791Sdim } 268243791Sdim 269243791Sdim void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { 270243791Sdim if (DisableReplaceStmt) 271243791Sdim return; 272243791Sdim 273243791Sdim // Measure the old text. 274243791Sdim int Size = Rewrite.getRangeSize(SrcRange); 275243791Sdim if (Size == -1) { 276243791Sdim Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 277243791Sdim << Old->getSourceRange(); 278243791Sdim return; 279243791Sdim } 280243791Sdim // Get the new text. 281243791Sdim std::string SStr; 282243791Sdim llvm::raw_string_ostream S(SStr); 283243791Sdim New->printPretty(S, 0, PrintingPolicy(LangOpts)); 284243791Sdim const std::string &Str = S.str(); 285243791Sdim 286243791Sdim // If replacement succeeded or warning disabled return with no warning. 287243791Sdim if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) { 288243791Sdim ReplacedNodes[Old] = New; 289243791Sdim return; 290243791Sdim } 291243791Sdim if (SilenceRewriteMacroWarning) 292243791Sdim return; 293243791Sdim Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 294243791Sdim << Old->getSourceRange(); 295243791Sdim } 296243791Sdim 297243791Sdim void InsertText(SourceLocation Loc, StringRef Str, 298243791Sdim bool InsertAfter = true) { 299243791Sdim // If insertion succeeded or warning disabled return with no warning. 300243791Sdim if (!Rewrite.InsertText(Loc, Str, InsertAfter) || 301243791Sdim SilenceRewriteMacroWarning) 302243791Sdim return; 303243791Sdim 304243791Sdim Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 305243791Sdim } 306243791Sdim 307243791Sdim void ReplaceText(SourceLocation Start, unsigned OrigLength, 308243791Sdim StringRef Str) { 309243791Sdim // If removal succeeded or warning disabled return with no warning. 310243791Sdim if (!Rewrite.ReplaceText(Start, OrigLength, Str) || 311243791Sdim SilenceRewriteMacroWarning) 312243791Sdim return; 313243791Sdim 314243791Sdim Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); 315243791Sdim } 316243791Sdim 317243791Sdim // Syntactic Rewriting. 318243791Sdim void RewriteRecordBody(RecordDecl *RD); 319243791Sdim void RewriteInclude(); 320243791Sdim void RewriteLineDirective(const Decl *D); 321243791Sdim void ConvertSourceLocationToLineDirective(SourceLocation Loc, 322243791Sdim std::string &LineString); 323243791Sdim void RewriteForwardClassDecl(DeclGroupRef D); 324263508Sdim void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG); 325243791Sdim void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 326243791Sdim const std::string &typedefString); 327243791Sdim void RewriteImplementations(); 328243791Sdim void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 329243791Sdim ObjCImplementationDecl *IMD, 330243791Sdim ObjCCategoryImplDecl *CID); 331243791Sdim void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); 332243791Sdim void RewriteImplementationDecl(Decl *Dcl); 333243791Sdim void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 334243791Sdim ObjCMethodDecl *MDecl, std::string &ResultStr); 335243791Sdim void RewriteTypeIntoString(QualType T, std::string &ResultStr, 336243791Sdim const FunctionType *&FPRetType); 337243791Sdim void RewriteByRefString(std::string &ResultStr, const std::string &Name, 338243791Sdim ValueDecl *VD, bool def=false); 339243791Sdim void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); 340243791Sdim void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); 341243791Sdim void RewriteForwardProtocolDecl(DeclGroupRef D); 342263508Sdim void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG); 343243791Sdim void RewriteMethodDeclaration(ObjCMethodDecl *Method); 344243791Sdim void RewriteProperty(ObjCPropertyDecl *prop); 345243791Sdim void RewriteFunctionDecl(FunctionDecl *FD); 346243791Sdim void RewriteBlockPointerType(std::string& Str, QualType Type); 347243791Sdim void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD); 348243791Sdim void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); 349243791Sdim void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); 350243791Sdim void RewriteTypeOfDecl(VarDecl *VD); 351243791Sdim void RewriteObjCQualifiedInterfaceTypes(Expr *E); 352243791Sdim 353243791Sdim std::string getIvarAccessString(ObjCIvarDecl *D); 354243791Sdim 355243791Sdim // Expression Rewriting. 356243791Sdim Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); 357243791Sdim Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); 358243791Sdim Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo); 359243791Sdim Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo); 360243791Sdim Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); 361243791Sdim Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); 362243791Sdim Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); 363243791Sdim Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp); 364243791Sdim Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp); 365243791Sdim Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp); 366243791Sdim Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp); 367243791Sdim Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); 368243791Sdim Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); 369243791Sdim Stmt *RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S); 370243791Sdim Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); 371243791Sdim Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); 372243791Sdim Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 373243791Sdim SourceLocation OrigEnd); 374243791Sdim Stmt *RewriteBreakStmt(BreakStmt *S); 375243791Sdim Stmt *RewriteContinueStmt(ContinueStmt *S); 376243791Sdim void RewriteCastExpr(CStyleCastExpr *CE); 377243791Sdim void RewriteImplicitCastObjCExpr(CastExpr *IE); 378243791Sdim void RewriteLinkageSpec(LinkageSpecDecl *LSD); 379243791Sdim 380249423Sdim // Computes ivar bitfield group no. 381249423Sdim unsigned ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV); 382249423Sdim // Names field decl. for ivar bitfield group. 383249423Sdim void ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, std::string &Result); 384249423Sdim // Names struct type for ivar bitfield group. 385249423Sdim void ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, std::string &Result); 386249423Sdim // Names symbol for ivar bitfield group field offset. 387249423Sdim void ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, std::string &Result); 388249423Sdim // Given an ivar bitfield, it builds (or finds) its group record type. 389249423Sdim QualType GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV); 390249423Sdim QualType SynthesizeBitfieldGroupStructType( 391249423Sdim ObjCIvarDecl *IV, 392249423Sdim SmallVectorImpl<ObjCIvarDecl *> &IVars); 393249423Sdim 394243791Sdim // Block rewriting. 395243791Sdim void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); 396243791Sdim 397243791Sdim // Block specific rewrite rules. 398243791Sdim void RewriteBlockPointerDecl(NamedDecl *VD); 399243791Sdim void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl); 400243791Sdim Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD); 401243791Sdim Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); 402243791Sdim void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); 403243791Sdim 404243791Sdim void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 405243791Sdim std::string &Result); 406243791Sdim 407243791Sdim void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result); 408243791Sdim bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag, 409243791Sdim bool &IsNamedDefinition); 410243791Sdim void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl, 411243791Sdim std::string &Result); 412243791Sdim 413243791Sdim bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result); 414243791Sdim 415243791Sdim void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, 416243791Sdim std::string &Result); 417243791Sdim 418243791Sdim virtual void Initialize(ASTContext &context); 419243791Sdim 420243791Sdim // Misc. AST transformation routines. Sometimes they end up calling 421243791Sdim // rewriting routines on the new ASTs. 422243791Sdim CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 423243791Sdim Expr **args, unsigned nargs, 424243791Sdim SourceLocation StartLoc=SourceLocation(), 425243791Sdim SourceLocation EndLoc=SourceLocation()); 426243791Sdim 427243791Sdim Expr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, 428243791Sdim QualType returnType, 429243791Sdim SmallVectorImpl<QualType> &ArgTypes, 430243791Sdim SmallVectorImpl<Expr*> &MsgExprs, 431243791Sdim ObjCMethodDecl *Method); 432243791Sdim 433243791Sdim Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, 434243791Sdim SourceLocation StartLoc=SourceLocation(), 435243791Sdim SourceLocation EndLoc=SourceLocation()); 436243791Sdim 437243791Sdim void SynthCountByEnumWithState(std::string &buf); 438243791Sdim void SynthMsgSendFunctionDecl(); 439243791Sdim void SynthMsgSendSuperFunctionDecl(); 440243791Sdim void SynthMsgSendStretFunctionDecl(); 441243791Sdim void SynthMsgSendFpretFunctionDecl(); 442243791Sdim void SynthMsgSendSuperStretFunctionDecl(); 443243791Sdim void SynthGetClassFunctionDecl(); 444243791Sdim void SynthGetMetaClassFunctionDecl(); 445243791Sdim void SynthGetSuperClassFunctionDecl(); 446243791Sdim void SynthSelGetUidFunctionDecl(); 447263508Sdim void SynthSuperConstructorFunctionDecl(); 448243791Sdim 449243791Sdim // Rewriting metadata 450243791Sdim template<typename MethodIterator> 451243791Sdim void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 452243791Sdim MethodIterator MethodEnd, 453243791Sdim bool IsInstanceMethod, 454243791Sdim StringRef prefix, 455243791Sdim StringRef ClassName, 456243791Sdim std::string &Result); 457243791Sdim void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 458243791Sdim std::string &Result); 459243791Sdim void RewriteObjCProtocolListMetaData( 460243791Sdim const ObjCList<ObjCProtocolDecl> &Prots, 461243791Sdim StringRef prefix, StringRef ClassName, std::string &Result); 462243791Sdim void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 463243791Sdim std::string &Result); 464243791Sdim void RewriteClassSetupInitHook(std::string &Result); 465243791Sdim 466243791Sdim void RewriteMetaDataIntoBuffer(std::string &Result); 467243791Sdim void WriteImageInfo(std::string &Result); 468243791Sdim void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 469243791Sdim std::string &Result); 470243791Sdim void RewriteCategorySetupInitHook(std::string &Result); 471243791Sdim 472243791Sdim // Rewriting ivar 473243791Sdim void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 474243791Sdim std::string &Result); 475243791Sdim Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV); 476243791Sdim 477243791Sdim 478243791Sdim std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); 479243791Sdim std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 480243791Sdim StringRef funcName, std::string Tag); 481243791Sdim std::string SynthesizeBlockFunc(BlockExpr *CE, int i, 482243791Sdim StringRef funcName, std::string Tag); 483243791Sdim std::string SynthesizeBlockImpl(BlockExpr *CE, 484243791Sdim std::string Tag, std::string Desc); 485243791Sdim std::string SynthesizeBlockDescriptor(std::string DescTag, 486243791Sdim std::string ImplTag, 487243791Sdim int i, StringRef funcName, 488243791Sdim unsigned hasCopy); 489243791Sdim Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); 490243791Sdim void SynthesizeBlockLiterals(SourceLocation FunLocStart, 491243791Sdim StringRef FunName); 492243791Sdim FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); 493243791Sdim Stmt *SynthBlockInitExpr(BlockExpr *Exp, 494263508Sdim const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs); 495243791Sdim 496243791Sdim // Misc. helper routines. 497243791Sdim QualType getProtocolType(); 498243791Sdim void WarnAboutReturnGotoStmts(Stmt *S); 499243791Sdim void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); 500243791Sdim void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); 501243791Sdim void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); 502243791Sdim 503243791Sdim bool IsDeclStmtInForeachHeader(DeclStmt *DS); 504243791Sdim void CollectBlockDeclRefInfo(BlockExpr *Exp); 505243791Sdim void GetBlockDeclRefExprs(Stmt *S); 506263508Sdim void GetInnerBlockDeclRefExprs(Stmt *S, 507263508Sdim SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs, 508243791Sdim llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts); 509243791Sdim 510243791Sdim // We avoid calling Type::isBlockPointerType(), since it operates on the 511243791Sdim // canonical type. We only care if the top-level type is a closure pointer. 512243791Sdim bool isTopLevelBlockPointerType(QualType T) { 513243791Sdim return isa<BlockPointerType>(T); 514243791Sdim } 515243791Sdim 516243791Sdim /// convertBlockPointerToFunctionPointer - Converts a block-pointer type 517243791Sdim /// to a function pointer type and upon success, returns true; false 518243791Sdim /// otherwise. 519243791Sdim bool convertBlockPointerToFunctionPointer(QualType &T) { 520243791Sdim if (isTopLevelBlockPointerType(T)) { 521243791Sdim const BlockPointerType *BPT = T->getAs<BlockPointerType>(); 522243791Sdim T = Context->getPointerType(BPT->getPointeeType()); 523243791Sdim return true; 524243791Sdim } 525243791Sdim return false; 526243791Sdim } 527243791Sdim 528243791Sdim bool convertObjCTypeToCStyleType(QualType &T); 529243791Sdim 530243791Sdim bool needToScanForQualifiers(QualType T); 531243791Sdim QualType getSuperStructType(); 532243791Sdim QualType getConstantStringStructType(); 533243791Sdim QualType convertFunctionTypeOfBlocks(const FunctionType *FT); 534243791Sdim bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); 535243791Sdim 536243791Sdim void convertToUnqualifiedObjCType(QualType &T) { 537243791Sdim if (T->isObjCQualifiedIdType()) { 538243791Sdim bool isConst = T.isConstQualified(); 539243791Sdim T = isConst ? Context->getObjCIdType().withConst() 540243791Sdim : Context->getObjCIdType(); 541243791Sdim } 542243791Sdim else if (T->isObjCQualifiedClassType()) 543243791Sdim T = Context->getObjCClassType(); 544243791Sdim else if (T->isObjCObjectPointerType() && 545243791Sdim T->getPointeeType()->isObjCQualifiedInterfaceType()) { 546243791Sdim if (const ObjCObjectPointerType * OBJPT = 547243791Sdim T->getAsObjCInterfacePointerType()) { 548243791Sdim const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); 549243791Sdim T = QualType(IFaceT, 0); 550243791Sdim T = Context->getPointerType(T); 551243791Sdim } 552243791Sdim } 553243791Sdim } 554243791Sdim 555243791Sdim // FIXME: This predicate seems like it would be useful to add to ASTContext. 556243791Sdim bool isObjCType(QualType T) { 557243791Sdim if (!LangOpts.ObjC1 && !LangOpts.ObjC2) 558243791Sdim return false; 559243791Sdim 560243791Sdim QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); 561243791Sdim 562243791Sdim if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || 563243791Sdim OCT == Context->getCanonicalType(Context->getObjCClassType())) 564243791Sdim return true; 565243791Sdim 566243791Sdim if (const PointerType *PT = OCT->getAs<PointerType>()) { 567243791Sdim if (isa<ObjCInterfaceType>(PT->getPointeeType()) || 568243791Sdim PT->getPointeeType()->isObjCQualifiedIdType()) 569243791Sdim return true; 570243791Sdim } 571243791Sdim return false; 572243791Sdim } 573243791Sdim bool PointerTypeTakesAnyBlockArguments(QualType QT); 574243791Sdim bool PointerTypeTakesAnyObjCQualifiedType(QualType QT); 575243791Sdim void GetExtentOfArgList(const char *Name, const char *&LParen, 576243791Sdim const char *&RParen); 577243791Sdim 578243791Sdim void QuoteDoublequotes(std::string &From, std::string &To) { 579243791Sdim for (unsigned i = 0; i < From.length(); i++) { 580243791Sdim if (From[i] == '"') 581243791Sdim To += "\\\""; 582243791Sdim else 583243791Sdim To += From[i]; 584243791Sdim } 585243791Sdim } 586243791Sdim 587243791Sdim QualType getSimpleFunctionType(QualType result, 588249423Sdim ArrayRef<QualType> args, 589243791Sdim bool variadic = false) { 590243791Sdim if (result == Context->getObjCInstanceType()) 591243791Sdim result = Context->getObjCIdType(); 592243791Sdim FunctionProtoType::ExtProtoInfo fpi; 593243791Sdim fpi.Variadic = variadic; 594249423Sdim return Context->getFunctionType(result, args, fpi); 595243791Sdim } 596243791Sdim 597243791Sdim // Helper function: create a CStyleCastExpr with trivial type source info. 598243791Sdim CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, 599243791Sdim CastKind Kind, Expr *E) { 600243791Sdim TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); 601243791Sdim return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo, 602243791Sdim SourceLocation(), SourceLocation()); 603243791Sdim } 604243791Sdim 605243791Sdim bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const { 606243791Sdim IdentifierInfo* II = &Context->Idents.get("load"); 607243791Sdim Selector LoadSel = Context->Selectors.getSelector(0, &II); 608243791Sdim return OD->getClassMethod(LoadSel) != 0; 609243791Sdim } 610243791Sdim }; 611243791Sdim 612243791Sdim} 613243791Sdim 614243791Sdimvoid RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType, 615243791Sdim NamedDecl *D) { 616243791Sdim if (const FunctionProtoType *fproto 617243791Sdim = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) { 618243791Sdim for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), 619243791Sdim E = fproto->arg_type_end(); I && (I != E); ++I) 620243791Sdim if (isTopLevelBlockPointerType(*I)) { 621243791Sdim // All the args are checked/rewritten. Don't call twice! 622243791Sdim RewriteBlockPointerDecl(D); 623243791Sdim break; 624243791Sdim } 625243791Sdim } 626243791Sdim} 627243791Sdim 628243791Sdimvoid RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { 629243791Sdim const PointerType *PT = funcType->getAs<PointerType>(); 630243791Sdim if (PT && PointerTypeTakesAnyBlockArguments(funcType)) 631243791Sdim RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); 632243791Sdim} 633243791Sdim 634243791Sdimstatic bool IsHeaderFile(const std::string &Filename) { 635243791Sdim std::string::size_type DotPos = Filename.rfind('.'); 636243791Sdim 637243791Sdim if (DotPos == std::string::npos) { 638243791Sdim // no file extension 639243791Sdim return false; 640243791Sdim } 641243791Sdim 642243791Sdim std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); 643243791Sdim // C header: .h 644243791Sdim // C++ header: .hh or .H; 645243791Sdim return Ext == "h" || Ext == "hh" || Ext == "H"; 646243791Sdim} 647243791Sdim 648243791SdimRewriteModernObjC::RewriteModernObjC(std::string inFile, raw_ostream* OS, 649243791Sdim DiagnosticsEngine &D, const LangOptions &LOpts, 650249423Sdim bool silenceMacroWarn, 651249423Sdim bool LineInfo) 652243791Sdim : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS), 653249423Sdim SilenceRewriteMacroWarning(silenceMacroWarn), GenerateLineInfo(LineInfo) { 654243791Sdim IsHeader = IsHeaderFile(inFile); 655243791Sdim RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 656243791Sdim "rewriting sub-expression within a macro (may not be correct)"); 657243791Sdim // FIXME. This should be an error. But if block is not called, it is OK. And it 658243791Sdim // may break including some headers. 659243791Sdim GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 660243791Sdim "rewriting block literal declared in global scope is not implemented"); 661243791Sdim 662243791Sdim TryFinallyContainsReturnDiag = Diags.getCustomDiagID( 663243791Sdim DiagnosticsEngine::Warning, 664243791Sdim "rewriter doesn't support user-specified control flow semantics " 665243791Sdim "for @try/@finally (code may not execute properly)"); 666243791Sdim} 667243791Sdim 668243791SdimASTConsumer *clang::CreateModernObjCRewriter(const std::string& InFile, 669243791Sdim raw_ostream* OS, 670243791Sdim DiagnosticsEngine &Diags, 671243791Sdim const LangOptions &LOpts, 672249423Sdim bool SilenceRewriteMacroWarning, 673249423Sdim bool LineInfo) { 674249423Sdim return new RewriteModernObjC(InFile, OS, Diags, LOpts, 675249423Sdim SilenceRewriteMacroWarning, LineInfo); 676243791Sdim} 677243791Sdim 678243791Sdimvoid RewriteModernObjC::InitializeCommon(ASTContext &context) { 679243791Sdim Context = &context; 680243791Sdim SM = &Context->getSourceManager(); 681243791Sdim TUDecl = Context->getTranslationUnitDecl(); 682243791Sdim MsgSendFunctionDecl = 0; 683243791Sdim MsgSendSuperFunctionDecl = 0; 684243791Sdim MsgSendStretFunctionDecl = 0; 685243791Sdim MsgSendSuperStretFunctionDecl = 0; 686243791Sdim MsgSendFpretFunctionDecl = 0; 687243791Sdim GetClassFunctionDecl = 0; 688243791Sdim GetMetaClassFunctionDecl = 0; 689243791Sdim GetSuperClassFunctionDecl = 0; 690243791Sdim SelGetUidFunctionDecl = 0; 691243791Sdim CFStringFunctionDecl = 0; 692243791Sdim ConstantStringClassReference = 0; 693243791Sdim NSStringRecord = 0; 694243791Sdim CurMethodDef = 0; 695243791Sdim CurFunctionDef = 0; 696243791Sdim GlobalVarDecl = 0; 697243791Sdim GlobalConstructionExp = 0; 698243791Sdim SuperStructDecl = 0; 699243791Sdim ProtocolTypeDecl = 0; 700243791Sdim ConstantStringDecl = 0; 701243791Sdim BcLabelCount = 0; 702263508Sdim SuperConstructorFunctionDecl = 0; 703243791Sdim NumObjCStringLiterals = 0; 704243791Sdim PropParentMap = 0; 705243791Sdim CurrentBody = 0; 706243791Sdim DisableReplaceStmt = false; 707243791Sdim objc_impl_method = false; 708243791Sdim 709243791Sdim // Get the ID and start/end of the main file. 710243791Sdim MainFileID = SM->getMainFileID(); 711243791Sdim const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID); 712243791Sdim MainFileStart = MainBuf->getBufferStart(); 713243791Sdim MainFileEnd = MainBuf->getBufferEnd(); 714243791Sdim 715243791Sdim Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts()); 716243791Sdim} 717243791Sdim 718243791Sdim//===----------------------------------------------------------------------===// 719243791Sdim// Top Level Driver Code 720243791Sdim//===----------------------------------------------------------------------===// 721243791Sdim 722243791Sdimvoid RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) { 723243791Sdim if (Diags.hasErrorOccurred()) 724243791Sdim return; 725243791Sdim 726243791Sdim // Two cases: either the decl could be in the main file, or it could be in a 727243791Sdim // #included file. If the former, rewrite it now. If the later, check to see 728243791Sdim // if we rewrote the #include/#import. 729243791Sdim SourceLocation Loc = D->getLocation(); 730243791Sdim Loc = SM->getExpansionLoc(Loc); 731243791Sdim 732243791Sdim // If this is for a builtin, ignore it. 733243791Sdim if (Loc.isInvalid()) return; 734243791Sdim 735243791Sdim // Look for built-in declarations that we need to refer during the rewrite. 736243791Sdim if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 737243791Sdim RewriteFunctionDecl(FD); 738243791Sdim } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) { 739243791Sdim // declared in <Foundation/NSString.h> 740243791Sdim if (FVD->getName() == "_NSConstantStringClassReference") { 741243791Sdim ConstantStringClassReference = FVD; 742243791Sdim return; 743243791Sdim } 744243791Sdim } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { 745243791Sdim RewriteCategoryDecl(CD); 746243791Sdim } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { 747243791Sdim if (PD->isThisDeclarationADefinition()) 748243791Sdim RewriteProtocolDecl(PD); 749243791Sdim } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { 750243791Sdim // FIXME. This will not work in all situations and leaving it out 751243791Sdim // is harmless. 752243791Sdim // RewriteLinkageSpec(LSD); 753243791Sdim 754243791Sdim // Recurse into linkage specifications 755243791Sdim for (DeclContext::decl_iterator DI = LSD->decls_begin(), 756243791Sdim DIEnd = LSD->decls_end(); 757243791Sdim DI != DIEnd; ) { 758243791Sdim if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) { 759243791Sdim if (!IFace->isThisDeclarationADefinition()) { 760243791Sdim SmallVector<Decl *, 8> DG; 761243791Sdim SourceLocation StartLoc = IFace->getLocStart(); 762243791Sdim do { 763243791Sdim if (isa<ObjCInterfaceDecl>(*DI) && 764243791Sdim !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() && 765243791Sdim StartLoc == (*DI)->getLocStart()) 766243791Sdim DG.push_back(*DI); 767243791Sdim else 768243791Sdim break; 769243791Sdim 770243791Sdim ++DI; 771243791Sdim } while (DI != DIEnd); 772243791Sdim RewriteForwardClassDecl(DG); 773243791Sdim continue; 774243791Sdim } 775243791Sdim else { 776243791Sdim // Keep track of all interface declarations seen. 777243791Sdim ObjCInterfacesSeen.push_back(IFace); 778243791Sdim ++DI; 779243791Sdim continue; 780243791Sdim } 781243791Sdim } 782243791Sdim 783243791Sdim if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) { 784243791Sdim if (!Proto->isThisDeclarationADefinition()) { 785243791Sdim SmallVector<Decl *, 8> DG; 786243791Sdim SourceLocation StartLoc = Proto->getLocStart(); 787243791Sdim do { 788243791Sdim if (isa<ObjCProtocolDecl>(*DI) && 789243791Sdim !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() && 790243791Sdim StartLoc == (*DI)->getLocStart()) 791243791Sdim DG.push_back(*DI); 792243791Sdim else 793243791Sdim break; 794243791Sdim 795243791Sdim ++DI; 796243791Sdim } while (DI != DIEnd); 797243791Sdim RewriteForwardProtocolDecl(DG); 798243791Sdim continue; 799243791Sdim } 800243791Sdim } 801243791Sdim 802243791Sdim HandleTopLevelSingleDecl(*DI); 803243791Sdim ++DI; 804243791Sdim } 805243791Sdim } 806243791Sdim // If we have a decl in the main file, see if we should rewrite it. 807263508Sdim if (SM->isWrittenInMainFile(Loc)) 808243791Sdim return HandleDeclInMainFile(D); 809243791Sdim} 810243791Sdim 811243791Sdim//===----------------------------------------------------------------------===// 812243791Sdim// Syntactic (non-AST) Rewriting Code 813243791Sdim//===----------------------------------------------------------------------===// 814243791Sdim 815243791Sdimvoid RewriteModernObjC::RewriteInclude() { 816243791Sdim SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); 817243791Sdim StringRef MainBuf = SM->getBufferData(MainFileID); 818243791Sdim const char *MainBufStart = MainBuf.begin(); 819243791Sdim const char *MainBufEnd = MainBuf.end(); 820243791Sdim size_t ImportLen = strlen("import"); 821243791Sdim 822243791Sdim // Loop over the whole file, looking for includes. 823243791Sdim for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { 824243791Sdim if (*BufPtr == '#') { 825243791Sdim if (++BufPtr == MainBufEnd) 826243791Sdim return; 827243791Sdim while (*BufPtr == ' ' || *BufPtr == '\t') 828243791Sdim if (++BufPtr == MainBufEnd) 829243791Sdim return; 830243791Sdim if (!strncmp(BufPtr, "import", ImportLen)) { 831243791Sdim // replace import with include 832243791Sdim SourceLocation ImportLoc = 833243791Sdim LocStart.getLocWithOffset(BufPtr-MainBufStart); 834243791Sdim ReplaceText(ImportLoc, ImportLen, "include"); 835243791Sdim BufPtr += ImportLen; 836243791Sdim } 837243791Sdim } 838243791Sdim } 839243791Sdim} 840243791Sdim 841243791Sdimstatic void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl, 842243791Sdim ObjCIvarDecl *IvarDecl, std::string &Result) { 843243791Sdim Result += "OBJC_IVAR_$_"; 844243791Sdim Result += IDecl->getName(); 845243791Sdim Result += "$"; 846243791Sdim Result += IvarDecl->getName(); 847243791Sdim} 848243791Sdim 849243791Sdimstd::string 850243791SdimRewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { 851243791Sdim const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface(); 852243791Sdim 853243791Sdim // Build name of symbol holding ivar offset. 854243791Sdim std::string IvarOffsetName; 855249423Sdim if (D->isBitField()) 856249423Sdim ObjCIvarBitfieldGroupOffset(D, IvarOffsetName); 857249423Sdim else 858249423Sdim WriteInternalIvarName(ClassDecl, D, IvarOffsetName); 859243791Sdim 860243791Sdim 861243791Sdim std::string S = "(*("; 862243791Sdim QualType IvarT = D->getType(); 863249423Sdim if (D->isBitField()) 864249423Sdim IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); 865243791Sdim 866243791Sdim if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) { 867243791Sdim RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl(); 868243791Sdim RD = RD->getDefinition(); 869243791Sdim if (RD && !RD->getDeclName().getAsIdentifierInfo()) { 870243791Sdim // decltype(((Foo_IMPL*)0)->bar) * 871243791Sdim ObjCContainerDecl *CDecl = 872243791Sdim dyn_cast<ObjCContainerDecl>(D->getDeclContext()); 873243791Sdim // ivar in class extensions requires special treatment. 874243791Sdim if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 875243791Sdim CDecl = CatDecl->getClassInterface(); 876243791Sdim std::string RecName = CDecl->getName(); 877243791Sdim RecName += "_IMPL"; 878243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 879243791Sdim SourceLocation(), SourceLocation(), 880243791Sdim &Context->Idents.get(RecName.c_str())); 881243791Sdim QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD)); 882243791Sdim unsigned UnsignedIntSize = 883243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 884243791Sdim Expr *Zero = IntegerLiteral::Create(*Context, 885243791Sdim llvm::APInt(UnsignedIntSize, 0), 886243791Sdim Context->UnsignedIntTy, SourceLocation()); 887243791Sdim Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero); 888243791Sdim ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 889243791Sdim Zero); 890243791Sdim FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 891243791Sdim SourceLocation(), 892243791Sdim &Context->Idents.get(D->getNameAsString()), 893243791Sdim IvarT, 0, 894243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 895243791Sdim ICIS_NoInit); 896243791Sdim MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 897243791Sdim FD->getType(), VK_LValue, 898243791Sdim OK_Ordinary); 899243791Sdim IvarT = Context->getDecltypeType(ME, ME->getType()); 900243791Sdim } 901243791Sdim } 902243791Sdim convertObjCTypeToCStyleType(IvarT); 903243791Sdim QualType castT = Context->getPointerType(IvarT); 904243791Sdim std::string TypeString(castT.getAsString(Context->getPrintingPolicy())); 905243791Sdim S += TypeString; 906243791Sdim S += ")"; 907243791Sdim 908243791Sdim // ((char *)self + IVAR_OFFSET_SYMBOL_NAME) 909243791Sdim S += "((char *)self + "; 910243791Sdim S += IvarOffsetName; 911243791Sdim S += "))"; 912249423Sdim if (D->isBitField()) { 913249423Sdim S += "."; 914249423Sdim S += D->getNameAsString(); 915249423Sdim } 916243791Sdim ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D); 917243791Sdim return S; 918243791Sdim} 919243791Sdim 920243791Sdim/// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not 921243791Sdim/// been found in the class implementation. In this case, it must be synthesized. 922243791Sdimstatic bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP, 923243791Sdim ObjCPropertyDecl *PD, 924243791Sdim bool getter) { 925243791Sdim return getter ? !IMP->getInstanceMethod(PD->getGetterName()) 926243791Sdim : !IMP->getInstanceMethod(PD->getSetterName()); 927243791Sdim 928243791Sdim} 929243791Sdim 930243791Sdimvoid RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 931243791Sdim ObjCImplementationDecl *IMD, 932243791Sdim ObjCCategoryImplDecl *CID) { 933243791Sdim static bool objcGetPropertyDefined = false; 934243791Sdim static bool objcSetPropertyDefined = false; 935243791Sdim SourceLocation startGetterSetterLoc; 936243791Sdim 937243791Sdim if (PID->getLocStart().isValid()) { 938243791Sdim SourceLocation startLoc = PID->getLocStart(); 939243791Sdim InsertText(startLoc, "// "); 940243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 941243791Sdim assert((*startBuf == '@') && "bogus @synthesize location"); 942243791Sdim const char *semiBuf = strchr(startBuf, ';'); 943243791Sdim assert((*semiBuf == ';') && "@synthesize: can't find ';'"); 944243791Sdim startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 945243791Sdim } 946243791Sdim else 947243791Sdim startGetterSetterLoc = IMD ? IMD->getLocEnd() : CID->getLocEnd(); 948243791Sdim 949243791Sdim if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 950243791Sdim return; // FIXME: is this correct? 951243791Sdim 952243791Sdim // Generate the 'getter' function. 953243791Sdim ObjCPropertyDecl *PD = PID->getPropertyDecl(); 954243791Sdim ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); 955249423Sdim assert(IMD && OID && "Synthesized ivars must be attached to @implementation"); 956243791Sdim 957243791Sdim unsigned Attributes = PD->getPropertyAttributes(); 958243791Sdim if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) { 959243791Sdim bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) && 960243791Sdim (Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 961243791Sdim ObjCPropertyDecl::OBJC_PR_copy)); 962243791Sdim std::string Getr; 963243791Sdim if (GenGetProperty && !objcGetPropertyDefined) { 964243791Sdim objcGetPropertyDefined = true; 965243791Sdim // FIXME. Is this attribute correct in all cases? 966243791Sdim Getr = "\nextern \"C\" __declspec(dllimport) " 967243791Sdim "id objc_getProperty(id, SEL, long, bool);\n"; 968243791Sdim } 969243791Sdim RewriteObjCMethodDecl(OID->getContainingInterface(), 970243791Sdim PD->getGetterMethodDecl(), Getr); 971243791Sdim Getr += "{ "; 972243791Sdim // Synthesize an explicit cast to gain access to the ivar. 973243791Sdim // See objc-act.c:objc_synthesize_new_getter() for details. 974243791Sdim if (GenGetProperty) { 975243791Sdim // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) 976243791Sdim Getr += "typedef "; 977243791Sdim const FunctionType *FPRetType = 0; 978243791Sdim RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr, 979243791Sdim FPRetType); 980243791Sdim Getr += " _TYPE"; 981243791Sdim if (FPRetType) { 982243791Sdim Getr += ")"; // close the precedence "scope" for "*". 983243791Sdim 984243791Sdim // Now, emit the argument types (if any). 985243791Sdim if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){ 986243791Sdim Getr += "("; 987243791Sdim for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 988243791Sdim if (i) Getr += ", "; 989243791Sdim std::string ParamStr = FT->getArgType(i).getAsString( 990243791Sdim Context->getPrintingPolicy()); 991243791Sdim Getr += ParamStr; 992243791Sdim } 993243791Sdim if (FT->isVariadic()) { 994243791Sdim if (FT->getNumArgs()) Getr += ", "; 995243791Sdim Getr += "..."; 996243791Sdim } 997243791Sdim Getr += ")"; 998243791Sdim } else 999243791Sdim Getr += "()"; 1000243791Sdim } 1001243791Sdim Getr += ";\n"; 1002243791Sdim Getr += "return (_TYPE)"; 1003243791Sdim Getr += "objc_getProperty(self, _cmd, "; 1004243791Sdim RewriteIvarOffsetComputation(OID, Getr); 1005243791Sdim Getr += ", 1)"; 1006243791Sdim } 1007243791Sdim else 1008243791Sdim Getr += "return " + getIvarAccessString(OID); 1009243791Sdim Getr += "; }"; 1010243791Sdim InsertText(startGetterSetterLoc, Getr); 1011243791Sdim } 1012243791Sdim 1013243791Sdim if (PD->isReadOnly() || 1014243791Sdim !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/)) 1015243791Sdim return; 1016243791Sdim 1017243791Sdim // Generate the 'setter' function. 1018243791Sdim std::string Setr; 1019243791Sdim bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 1020243791Sdim ObjCPropertyDecl::OBJC_PR_copy); 1021243791Sdim if (GenSetProperty && !objcSetPropertyDefined) { 1022243791Sdim objcSetPropertyDefined = true; 1023243791Sdim // FIXME. Is this attribute correct in all cases? 1024243791Sdim Setr = "\nextern \"C\" __declspec(dllimport) " 1025243791Sdim "void objc_setProperty (id, SEL, long, id, bool, bool);\n"; 1026243791Sdim } 1027243791Sdim 1028243791Sdim RewriteObjCMethodDecl(OID->getContainingInterface(), 1029243791Sdim PD->getSetterMethodDecl(), Setr); 1030243791Sdim Setr += "{ "; 1031243791Sdim // Synthesize an explicit cast to initialize the ivar. 1032243791Sdim // See objc-act.c:objc_synthesize_new_setter() for details. 1033243791Sdim if (GenSetProperty) { 1034243791Sdim Setr += "objc_setProperty (self, _cmd, "; 1035243791Sdim RewriteIvarOffsetComputation(OID, Setr); 1036243791Sdim Setr += ", (id)"; 1037243791Sdim Setr += PD->getName(); 1038243791Sdim Setr += ", "; 1039243791Sdim if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) 1040243791Sdim Setr += "0, "; 1041243791Sdim else 1042243791Sdim Setr += "1, "; 1043243791Sdim if (Attributes & ObjCPropertyDecl::OBJC_PR_copy) 1044243791Sdim Setr += "1)"; 1045243791Sdim else 1046243791Sdim Setr += "0)"; 1047243791Sdim } 1048243791Sdim else { 1049243791Sdim Setr += getIvarAccessString(OID) + " = "; 1050243791Sdim Setr += PD->getName(); 1051243791Sdim } 1052243791Sdim Setr += "; }\n"; 1053243791Sdim InsertText(startGetterSetterLoc, Setr); 1054243791Sdim} 1055243791Sdim 1056243791Sdimstatic void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, 1057243791Sdim std::string &typedefString) { 1058249423Sdim typedefString += "\n#ifndef _REWRITER_typedef_"; 1059243791Sdim typedefString += ForwardDecl->getNameAsString(); 1060243791Sdim typedefString += "\n"; 1061243791Sdim typedefString += "#define _REWRITER_typedef_"; 1062243791Sdim typedefString += ForwardDecl->getNameAsString(); 1063243791Sdim typedefString += "\n"; 1064243791Sdim typedefString += "typedef struct objc_object "; 1065243791Sdim typedefString += ForwardDecl->getNameAsString(); 1066243791Sdim // typedef struct { } _objc_exc_Classname; 1067243791Sdim typedefString += ";\ntypedef struct {} _objc_exc_"; 1068243791Sdim typedefString += ForwardDecl->getNameAsString(); 1069243791Sdim typedefString += ";\n#endif\n"; 1070243791Sdim} 1071243791Sdim 1072243791Sdimvoid RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 1073243791Sdim const std::string &typedefString) { 1074243791Sdim SourceLocation startLoc = ClassDecl->getLocStart(); 1075243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1076243791Sdim const char *semiPtr = strchr(startBuf, ';'); 1077243791Sdim // Replace the @class with typedefs corresponding to the classes. 1078243791Sdim ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); 1079243791Sdim} 1080243791Sdim 1081243791Sdimvoid RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) { 1082243791Sdim std::string typedefString; 1083243791Sdim for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 1084263508Sdim if (ObjCInterfaceDecl *ForwardDecl = dyn_cast<ObjCInterfaceDecl>(*I)) { 1085263508Sdim if (I == D.begin()) { 1086263508Sdim // Translate to typedef's that forward reference structs with the same name 1087263508Sdim // as the class. As a convenience, we include the original declaration 1088263508Sdim // as a comment. 1089263508Sdim typedefString += "// @class "; 1090263508Sdim typedefString += ForwardDecl->getNameAsString(); 1091263508Sdim typedefString += ";"; 1092263508Sdim } 1093263508Sdim RewriteOneForwardClassDecl(ForwardDecl, typedefString); 1094243791Sdim } 1095263508Sdim else 1096263508Sdim HandleTopLevelSingleDecl(*I); 1097243791Sdim } 1098243791Sdim DeclGroupRef::iterator I = D.begin(); 1099243791Sdim RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString); 1100243791Sdim} 1101243791Sdim 1102243791Sdimvoid RewriteModernObjC::RewriteForwardClassDecl( 1103263508Sdim const SmallVectorImpl<Decl *> &D) { 1104243791Sdim std::string typedefString; 1105243791Sdim for (unsigned i = 0; i < D.size(); i++) { 1106243791Sdim ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]); 1107243791Sdim if (i == 0) { 1108243791Sdim typedefString += "// @class "; 1109243791Sdim typedefString += ForwardDecl->getNameAsString(); 1110249423Sdim typedefString += ";"; 1111243791Sdim } 1112243791Sdim RewriteOneForwardClassDecl(ForwardDecl, typedefString); 1113243791Sdim } 1114243791Sdim RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString); 1115243791Sdim} 1116243791Sdim 1117243791Sdimvoid RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { 1118243791Sdim // When method is a synthesized one, such as a getter/setter there is 1119243791Sdim // nothing to rewrite. 1120243791Sdim if (Method->isImplicit()) 1121243791Sdim return; 1122243791Sdim SourceLocation LocStart = Method->getLocStart(); 1123243791Sdim SourceLocation LocEnd = Method->getLocEnd(); 1124243791Sdim 1125243791Sdim if (SM->getExpansionLineNumber(LocEnd) > 1126243791Sdim SM->getExpansionLineNumber(LocStart)) { 1127243791Sdim InsertText(LocStart, "#if 0\n"); 1128243791Sdim ReplaceText(LocEnd, 1, ";\n#endif\n"); 1129243791Sdim } else { 1130243791Sdim InsertText(LocStart, "// "); 1131243791Sdim } 1132243791Sdim} 1133243791Sdim 1134243791Sdimvoid RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) { 1135243791Sdim SourceLocation Loc = prop->getAtLoc(); 1136243791Sdim 1137243791Sdim ReplaceText(Loc, 0, "// "); 1138243791Sdim // FIXME: handle properties that are declared across multiple lines. 1139243791Sdim} 1140243791Sdim 1141243791Sdimvoid RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { 1142243791Sdim SourceLocation LocStart = CatDecl->getLocStart(); 1143243791Sdim 1144243791Sdim // FIXME: handle category headers that are declared across multiple lines. 1145243791Sdim if (CatDecl->getIvarRBraceLoc().isValid()) { 1146243791Sdim ReplaceText(LocStart, 1, "/** "); 1147243791Sdim ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ "); 1148243791Sdim } 1149243791Sdim else { 1150243791Sdim ReplaceText(LocStart, 0, "// "); 1151243791Sdim } 1152243791Sdim 1153243791Sdim for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), 1154243791Sdim E = CatDecl->prop_end(); I != E; ++I) 1155243791Sdim RewriteProperty(*I); 1156243791Sdim 1157243791Sdim for (ObjCCategoryDecl::instmeth_iterator 1158243791Sdim I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); 1159243791Sdim I != E; ++I) 1160243791Sdim RewriteMethodDeclaration(*I); 1161243791Sdim for (ObjCCategoryDecl::classmeth_iterator 1162243791Sdim I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); 1163243791Sdim I != E; ++I) 1164243791Sdim RewriteMethodDeclaration(*I); 1165243791Sdim 1166243791Sdim // Lastly, comment out the @end. 1167243791Sdim ReplaceText(CatDecl->getAtEndRange().getBegin(), 1168249423Sdim strlen("@end"), "/* @end */\n"); 1169243791Sdim} 1170243791Sdim 1171243791Sdimvoid RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { 1172243791Sdim SourceLocation LocStart = PDecl->getLocStart(); 1173243791Sdim assert(PDecl->isThisDeclarationADefinition()); 1174243791Sdim 1175243791Sdim // FIXME: handle protocol headers that are declared across multiple lines. 1176243791Sdim ReplaceText(LocStart, 0, "// "); 1177243791Sdim 1178243791Sdim for (ObjCProtocolDecl::instmeth_iterator 1179243791Sdim I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 1180243791Sdim I != E; ++I) 1181243791Sdim RewriteMethodDeclaration(*I); 1182243791Sdim for (ObjCProtocolDecl::classmeth_iterator 1183243791Sdim I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 1184243791Sdim I != E; ++I) 1185243791Sdim RewriteMethodDeclaration(*I); 1186243791Sdim 1187243791Sdim for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(), 1188243791Sdim E = PDecl->prop_end(); I != E; ++I) 1189243791Sdim RewriteProperty(*I); 1190243791Sdim 1191243791Sdim // Lastly, comment out the @end. 1192243791Sdim SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); 1193249423Sdim ReplaceText(LocEnd, strlen("@end"), "/* @end */\n"); 1194243791Sdim 1195243791Sdim // Must comment out @optional/@required 1196243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 1197243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 1198243791Sdim for (const char *p = startBuf; p < endBuf; p++) { 1199243791Sdim if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { 1200243791Sdim SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 1201243791Sdim ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); 1202243791Sdim 1203243791Sdim } 1204243791Sdim else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { 1205243791Sdim SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 1206243791Sdim ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); 1207243791Sdim 1208243791Sdim } 1209243791Sdim } 1210243791Sdim} 1211243791Sdim 1212243791Sdimvoid RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) { 1213243791Sdim SourceLocation LocStart = (*D.begin())->getLocStart(); 1214243791Sdim if (LocStart.isInvalid()) 1215243791Sdim llvm_unreachable("Invalid SourceLocation"); 1216243791Sdim // FIXME: handle forward protocol that are declared across multiple lines. 1217243791Sdim ReplaceText(LocStart, 0, "// "); 1218243791Sdim} 1219243791Sdim 1220243791Sdimvoid 1221263508SdimRewriteModernObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) { 1222243791Sdim SourceLocation LocStart = DG[0]->getLocStart(); 1223243791Sdim if (LocStart.isInvalid()) 1224243791Sdim llvm_unreachable("Invalid SourceLocation"); 1225243791Sdim // FIXME: handle forward protocol that are declared across multiple lines. 1226243791Sdim ReplaceText(LocStart, 0, "// "); 1227243791Sdim} 1228243791Sdim 1229243791Sdimvoid 1230243791SdimRewriteModernObjC::RewriteLinkageSpec(LinkageSpecDecl *LSD) { 1231243791Sdim SourceLocation LocStart = LSD->getExternLoc(); 1232243791Sdim if (LocStart.isInvalid()) 1233243791Sdim llvm_unreachable("Invalid extern SourceLocation"); 1234243791Sdim 1235243791Sdim ReplaceText(LocStart, 0, "// "); 1236243791Sdim if (!LSD->hasBraces()) 1237243791Sdim return; 1238243791Sdim // FIXME. We don't rewrite well if '{' is not on same line as 'extern'. 1239243791Sdim SourceLocation LocRBrace = LSD->getRBraceLoc(); 1240243791Sdim if (LocRBrace.isInvalid()) 1241243791Sdim llvm_unreachable("Invalid rbrace SourceLocation"); 1242243791Sdim ReplaceText(LocRBrace, 0, "// "); 1243243791Sdim} 1244243791Sdim 1245243791Sdimvoid RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr, 1246243791Sdim const FunctionType *&FPRetType) { 1247243791Sdim if (T->isObjCQualifiedIdType()) 1248243791Sdim ResultStr += "id"; 1249243791Sdim else if (T->isFunctionPointerType() || 1250243791Sdim T->isBlockPointerType()) { 1251243791Sdim // needs special handling, since pointer-to-functions have special 1252243791Sdim // syntax (where a decaration models use). 1253243791Sdim QualType retType = T; 1254243791Sdim QualType PointeeTy; 1255243791Sdim if (const PointerType* PT = retType->getAs<PointerType>()) 1256243791Sdim PointeeTy = PT->getPointeeType(); 1257243791Sdim else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) 1258243791Sdim PointeeTy = BPT->getPointeeType(); 1259243791Sdim if ((FPRetType = PointeeTy->getAs<FunctionType>())) { 1260243791Sdim ResultStr += FPRetType->getResultType().getAsString( 1261243791Sdim Context->getPrintingPolicy()); 1262243791Sdim ResultStr += "(*"; 1263243791Sdim } 1264243791Sdim } else 1265243791Sdim ResultStr += T.getAsString(Context->getPrintingPolicy()); 1266243791Sdim} 1267243791Sdim 1268243791Sdimvoid RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 1269243791Sdim ObjCMethodDecl *OMD, 1270243791Sdim std::string &ResultStr) { 1271243791Sdim //fprintf(stderr,"In RewriteObjCMethodDecl\n"); 1272243791Sdim const FunctionType *FPRetType = 0; 1273243791Sdim ResultStr += "\nstatic "; 1274243791Sdim RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType); 1275243791Sdim ResultStr += " "; 1276243791Sdim 1277243791Sdim // Unique method name 1278243791Sdim std::string NameStr; 1279243791Sdim 1280243791Sdim if (OMD->isInstanceMethod()) 1281243791Sdim NameStr += "_I_"; 1282243791Sdim else 1283243791Sdim NameStr += "_C_"; 1284243791Sdim 1285243791Sdim NameStr += IDecl->getNameAsString(); 1286243791Sdim NameStr += "_"; 1287243791Sdim 1288243791Sdim if (ObjCCategoryImplDecl *CID = 1289243791Sdim dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 1290243791Sdim NameStr += CID->getNameAsString(); 1291243791Sdim NameStr += "_"; 1292243791Sdim } 1293243791Sdim // Append selector names, replacing ':' with '_' 1294243791Sdim { 1295243791Sdim std::string selString = OMD->getSelector().getAsString(); 1296243791Sdim int len = selString.size(); 1297243791Sdim for (int i = 0; i < len; i++) 1298243791Sdim if (selString[i] == ':') 1299243791Sdim selString[i] = '_'; 1300243791Sdim NameStr += selString; 1301243791Sdim } 1302243791Sdim // Remember this name for metadata emission 1303243791Sdim MethodInternalNames[OMD] = NameStr; 1304243791Sdim ResultStr += NameStr; 1305243791Sdim 1306243791Sdim // Rewrite arguments 1307243791Sdim ResultStr += "("; 1308243791Sdim 1309243791Sdim // invisible arguments 1310243791Sdim if (OMD->isInstanceMethod()) { 1311243791Sdim QualType selfTy = Context->getObjCInterfaceType(IDecl); 1312243791Sdim selfTy = Context->getPointerType(selfTy); 1313243791Sdim if (!LangOpts.MicrosoftExt) { 1314243791Sdim if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl))) 1315243791Sdim ResultStr += "struct "; 1316243791Sdim } 1317243791Sdim // When rewriting for Microsoft, explicitly omit the structure name. 1318243791Sdim ResultStr += IDecl->getNameAsString(); 1319243791Sdim ResultStr += " *"; 1320243791Sdim } 1321243791Sdim else 1322243791Sdim ResultStr += Context->getObjCClassType().getAsString( 1323243791Sdim Context->getPrintingPolicy()); 1324243791Sdim 1325243791Sdim ResultStr += " self, "; 1326243791Sdim ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy()); 1327243791Sdim ResultStr += " _cmd"; 1328243791Sdim 1329243791Sdim // Method arguments. 1330243791Sdim for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 1331243791Sdim E = OMD->param_end(); PI != E; ++PI) { 1332243791Sdim ParmVarDecl *PDecl = *PI; 1333243791Sdim ResultStr += ", "; 1334243791Sdim if (PDecl->getType()->isObjCQualifiedIdType()) { 1335243791Sdim ResultStr += "id "; 1336243791Sdim ResultStr += PDecl->getNameAsString(); 1337243791Sdim } else { 1338243791Sdim std::string Name = PDecl->getNameAsString(); 1339243791Sdim QualType QT = PDecl->getType(); 1340243791Sdim // Make sure we convert "t (^)(...)" to "t (*)(...)". 1341243791Sdim (void)convertBlockPointerToFunctionPointer(QT); 1342243791Sdim QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 1343243791Sdim ResultStr += Name; 1344243791Sdim } 1345243791Sdim } 1346243791Sdim if (OMD->isVariadic()) 1347243791Sdim ResultStr += ", ..."; 1348243791Sdim ResultStr += ") "; 1349243791Sdim 1350243791Sdim if (FPRetType) { 1351243791Sdim ResultStr += ")"; // close the precedence "scope" for "*". 1352243791Sdim 1353243791Sdim // Now, emit the argument types (if any). 1354243791Sdim if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { 1355243791Sdim ResultStr += "("; 1356243791Sdim for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 1357243791Sdim if (i) ResultStr += ", "; 1358243791Sdim std::string ParamStr = FT->getArgType(i).getAsString( 1359243791Sdim Context->getPrintingPolicy()); 1360243791Sdim ResultStr += ParamStr; 1361243791Sdim } 1362243791Sdim if (FT->isVariadic()) { 1363243791Sdim if (FT->getNumArgs()) ResultStr += ", "; 1364243791Sdim ResultStr += "..."; 1365243791Sdim } 1366243791Sdim ResultStr += ")"; 1367243791Sdim } else { 1368243791Sdim ResultStr += "()"; 1369243791Sdim } 1370243791Sdim } 1371243791Sdim} 1372243791Sdimvoid RewriteModernObjC::RewriteImplementationDecl(Decl *OID) { 1373243791Sdim ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); 1374243791Sdim ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); 1375243791Sdim 1376243791Sdim if (IMD) { 1377243791Sdim if (IMD->getIvarRBraceLoc().isValid()) { 1378243791Sdim ReplaceText(IMD->getLocStart(), 1, "/** "); 1379243791Sdim ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ "); 1380243791Sdim } 1381243791Sdim else { 1382243791Sdim InsertText(IMD->getLocStart(), "// "); 1383243791Sdim } 1384243791Sdim } 1385243791Sdim else 1386243791Sdim InsertText(CID->getLocStart(), "// "); 1387243791Sdim 1388243791Sdim for (ObjCCategoryImplDecl::instmeth_iterator 1389243791Sdim I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), 1390243791Sdim E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); 1391243791Sdim I != E; ++I) { 1392243791Sdim std::string ResultStr; 1393243791Sdim ObjCMethodDecl *OMD = *I; 1394243791Sdim RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 1395243791Sdim SourceLocation LocStart = OMD->getLocStart(); 1396243791Sdim SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 1397243791Sdim 1398243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 1399243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 1400243791Sdim ReplaceText(LocStart, endBuf-startBuf, ResultStr); 1401243791Sdim } 1402243791Sdim 1403243791Sdim for (ObjCCategoryImplDecl::classmeth_iterator 1404243791Sdim I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), 1405243791Sdim E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); 1406243791Sdim I != E; ++I) { 1407243791Sdim std::string ResultStr; 1408243791Sdim ObjCMethodDecl *OMD = *I; 1409243791Sdim RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 1410243791Sdim SourceLocation LocStart = OMD->getLocStart(); 1411243791Sdim SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 1412243791Sdim 1413243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 1414243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 1415243791Sdim ReplaceText(LocStart, endBuf-startBuf, ResultStr); 1416243791Sdim } 1417243791Sdim for (ObjCCategoryImplDecl::propimpl_iterator 1418243791Sdim I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), 1419243791Sdim E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); 1420243791Sdim I != E; ++I) { 1421243791Sdim RewritePropertyImplDecl(*I, IMD, CID); 1422243791Sdim } 1423243791Sdim 1424243791Sdim InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// "); 1425243791Sdim} 1426243791Sdim 1427243791Sdimvoid RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 1428243791Sdim // Do not synthesize more than once. 1429243791Sdim if (ObjCSynthesizedStructs.count(ClassDecl)) 1430243791Sdim return; 1431243791Sdim // Make sure super class's are written before current class is written. 1432243791Sdim ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass(); 1433243791Sdim while (SuperClass) { 1434243791Sdim RewriteInterfaceDecl(SuperClass); 1435243791Sdim SuperClass = SuperClass->getSuperClass(); 1436243791Sdim } 1437243791Sdim std::string ResultStr; 1438243791Sdim if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) { 1439243791Sdim // we haven't seen a forward decl - generate a typedef. 1440243791Sdim RewriteOneForwardClassDecl(ClassDecl, ResultStr); 1441243791Sdim RewriteIvarOffsetSymbols(ClassDecl, ResultStr); 1442243791Sdim 1443243791Sdim RewriteObjCInternalStruct(ClassDecl, ResultStr); 1444243791Sdim // Mark this typedef as having been written into its c++ equivalent. 1445243791Sdim ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl()); 1446243791Sdim 1447243791Sdim for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), 1448243791Sdim E = ClassDecl->prop_end(); I != E; ++I) 1449243791Sdim RewriteProperty(*I); 1450243791Sdim for (ObjCInterfaceDecl::instmeth_iterator 1451243791Sdim I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); 1452243791Sdim I != E; ++I) 1453243791Sdim RewriteMethodDeclaration(*I); 1454243791Sdim for (ObjCInterfaceDecl::classmeth_iterator 1455243791Sdim I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); 1456243791Sdim I != E; ++I) 1457243791Sdim RewriteMethodDeclaration(*I); 1458243791Sdim 1459243791Sdim // Lastly, comment out the @end. 1460243791Sdim ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), 1461249423Sdim "/* @end */\n"); 1462243791Sdim } 1463243791Sdim} 1464243791Sdim 1465243791SdimStmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) { 1466243791Sdim SourceRange OldRange = PseudoOp->getSourceRange(); 1467243791Sdim 1468243791Sdim // We just magically know some things about the structure of this 1469243791Sdim // expression. 1470243791Sdim ObjCMessageExpr *OldMsg = 1471243791Sdim cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr( 1472243791Sdim PseudoOp->getNumSemanticExprs() - 1)); 1473243791Sdim 1474243791Sdim // Because the rewriter doesn't allow us to rewrite rewritten code, 1475243791Sdim // we need to suppress rewriting the sub-statements. 1476243791Sdim Expr *Base; 1477243791Sdim SmallVector<Expr*, 2> Args; 1478243791Sdim { 1479243791Sdim DisableReplaceStmtScope S(*this); 1480243791Sdim 1481243791Sdim // Rebuild the base expression if we have one. 1482243791Sdim Base = 0; 1483243791Sdim if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 1484243791Sdim Base = OldMsg->getInstanceReceiver(); 1485243791Sdim Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 1486243791Sdim Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 1487243791Sdim } 1488243791Sdim 1489243791Sdim unsigned numArgs = OldMsg->getNumArgs(); 1490243791Sdim for (unsigned i = 0; i < numArgs; i++) { 1491243791Sdim Expr *Arg = OldMsg->getArg(i); 1492243791Sdim if (isa<OpaqueValueExpr>(Arg)) 1493243791Sdim Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr(); 1494243791Sdim Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg)); 1495243791Sdim Args.push_back(Arg); 1496243791Sdim } 1497243791Sdim } 1498243791Sdim 1499243791Sdim // TODO: avoid this copy. 1500243791Sdim SmallVector<SourceLocation, 1> SelLocs; 1501243791Sdim OldMsg->getSelectorLocs(SelLocs); 1502243791Sdim 1503243791Sdim ObjCMessageExpr *NewMsg = 0; 1504243791Sdim switch (OldMsg->getReceiverKind()) { 1505243791Sdim case ObjCMessageExpr::Class: 1506243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1507243791Sdim OldMsg->getValueKind(), 1508243791Sdim OldMsg->getLeftLoc(), 1509243791Sdim OldMsg->getClassReceiverTypeInfo(), 1510243791Sdim OldMsg->getSelector(), 1511243791Sdim SelLocs, 1512243791Sdim OldMsg->getMethodDecl(), 1513243791Sdim Args, 1514243791Sdim OldMsg->getRightLoc(), 1515243791Sdim OldMsg->isImplicit()); 1516243791Sdim break; 1517243791Sdim 1518243791Sdim case ObjCMessageExpr::Instance: 1519243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1520243791Sdim OldMsg->getValueKind(), 1521243791Sdim OldMsg->getLeftLoc(), 1522243791Sdim Base, 1523243791Sdim OldMsg->getSelector(), 1524243791Sdim SelLocs, 1525243791Sdim OldMsg->getMethodDecl(), 1526243791Sdim Args, 1527243791Sdim OldMsg->getRightLoc(), 1528243791Sdim OldMsg->isImplicit()); 1529243791Sdim break; 1530243791Sdim 1531243791Sdim case ObjCMessageExpr::SuperClass: 1532243791Sdim case ObjCMessageExpr::SuperInstance: 1533243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1534243791Sdim OldMsg->getValueKind(), 1535243791Sdim OldMsg->getLeftLoc(), 1536243791Sdim OldMsg->getSuperLoc(), 1537243791Sdim OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 1538243791Sdim OldMsg->getSuperType(), 1539243791Sdim OldMsg->getSelector(), 1540243791Sdim SelLocs, 1541243791Sdim OldMsg->getMethodDecl(), 1542243791Sdim Args, 1543243791Sdim OldMsg->getRightLoc(), 1544243791Sdim OldMsg->isImplicit()); 1545243791Sdim break; 1546243791Sdim } 1547243791Sdim 1548243791Sdim Stmt *Replacement = SynthMessageExpr(NewMsg); 1549243791Sdim ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 1550243791Sdim return Replacement; 1551243791Sdim} 1552243791Sdim 1553243791SdimStmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) { 1554243791Sdim SourceRange OldRange = PseudoOp->getSourceRange(); 1555243791Sdim 1556243791Sdim // We just magically know some things about the structure of this 1557243791Sdim // expression. 1558243791Sdim ObjCMessageExpr *OldMsg = 1559243791Sdim cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit()); 1560243791Sdim 1561243791Sdim // Because the rewriter doesn't allow us to rewrite rewritten code, 1562243791Sdim // we need to suppress rewriting the sub-statements. 1563243791Sdim Expr *Base = 0; 1564243791Sdim SmallVector<Expr*, 1> Args; 1565243791Sdim { 1566243791Sdim DisableReplaceStmtScope S(*this); 1567243791Sdim // Rebuild the base expression if we have one. 1568243791Sdim if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 1569243791Sdim Base = OldMsg->getInstanceReceiver(); 1570243791Sdim Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 1571243791Sdim Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 1572243791Sdim } 1573243791Sdim unsigned numArgs = OldMsg->getNumArgs(); 1574243791Sdim for (unsigned i = 0; i < numArgs; i++) { 1575243791Sdim Expr *Arg = OldMsg->getArg(i); 1576243791Sdim if (isa<OpaqueValueExpr>(Arg)) 1577243791Sdim Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr(); 1578243791Sdim Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg)); 1579243791Sdim Args.push_back(Arg); 1580243791Sdim } 1581243791Sdim } 1582243791Sdim 1583243791Sdim // Intentionally empty. 1584243791Sdim SmallVector<SourceLocation, 1> SelLocs; 1585243791Sdim 1586243791Sdim ObjCMessageExpr *NewMsg = 0; 1587243791Sdim switch (OldMsg->getReceiverKind()) { 1588243791Sdim case ObjCMessageExpr::Class: 1589243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1590243791Sdim OldMsg->getValueKind(), 1591243791Sdim OldMsg->getLeftLoc(), 1592243791Sdim OldMsg->getClassReceiverTypeInfo(), 1593243791Sdim OldMsg->getSelector(), 1594243791Sdim SelLocs, 1595243791Sdim OldMsg->getMethodDecl(), 1596243791Sdim Args, 1597243791Sdim OldMsg->getRightLoc(), 1598243791Sdim OldMsg->isImplicit()); 1599243791Sdim break; 1600243791Sdim 1601243791Sdim case ObjCMessageExpr::Instance: 1602243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1603243791Sdim OldMsg->getValueKind(), 1604243791Sdim OldMsg->getLeftLoc(), 1605243791Sdim Base, 1606243791Sdim OldMsg->getSelector(), 1607243791Sdim SelLocs, 1608243791Sdim OldMsg->getMethodDecl(), 1609243791Sdim Args, 1610243791Sdim OldMsg->getRightLoc(), 1611243791Sdim OldMsg->isImplicit()); 1612243791Sdim break; 1613243791Sdim 1614243791Sdim case ObjCMessageExpr::SuperClass: 1615243791Sdim case ObjCMessageExpr::SuperInstance: 1616243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1617243791Sdim OldMsg->getValueKind(), 1618243791Sdim OldMsg->getLeftLoc(), 1619243791Sdim OldMsg->getSuperLoc(), 1620243791Sdim OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 1621243791Sdim OldMsg->getSuperType(), 1622243791Sdim OldMsg->getSelector(), 1623243791Sdim SelLocs, 1624243791Sdim OldMsg->getMethodDecl(), 1625243791Sdim Args, 1626243791Sdim OldMsg->getRightLoc(), 1627243791Sdim OldMsg->isImplicit()); 1628243791Sdim break; 1629243791Sdim } 1630243791Sdim 1631243791Sdim Stmt *Replacement = SynthMessageExpr(NewMsg); 1632243791Sdim ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 1633243791Sdim return Replacement; 1634243791Sdim} 1635243791Sdim 1636243791Sdim/// SynthCountByEnumWithState - To print: 1637263508Sdim/// ((NSUInteger (*) 1638263508Sdim/// (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger)) 1639243791Sdim/// (void *)objc_msgSend)((id)l_collection, 1640243791Sdim/// sel_registerName( 1641243791Sdim/// "countByEnumeratingWithState:objects:count:"), 1642243791Sdim/// &enumState, 1643263508Sdim/// (id *)__rw_items, (NSUInteger)16) 1644243791Sdim/// 1645243791Sdimvoid RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) { 1646263508Sdim buf += "((_WIN_NSUInteger (*) (id, SEL, struct __objcFastEnumerationState *, " 1647263508Sdim "id *, _WIN_NSUInteger))(void *)objc_msgSend)"; 1648243791Sdim buf += "\n\t\t"; 1649243791Sdim buf += "((id)l_collection,\n\t\t"; 1650243791Sdim buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; 1651243791Sdim buf += "\n\t\t"; 1652243791Sdim buf += "&enumState, " 1653263508Sdim "(id *)__rw_items, (_WIN_NSUInteger)16)"; 1654243791Sdim} 1655243791Sdim 1656243791Sdim/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach 1657243791Sdim/// statement to exit to its outer synthesized loop. 1658243791Sdim/// 1659243791SdimStmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) { 1660243791Sdim if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1661243791Sdim return S; 1662243791Sdim // replace break with goto __break_label 1663243791Sdim std::string buf; 1664243791Sdim 1665243791Sdim SourceLocation startLoc = S->getLocStart(); 1666243791Sdim buf = "goto __break_label_"; 1667243791Sdim buf += utostr(ObjCBcLabelNo.back()); 1668243791Sdim ReplaceText(startLoc, strlen("break"), buf); 1669243791Sdim 1670243791Sdim return 0; 1671243791Sdim} 1672243791Sdim 1673243791Sdimvoid RewriteModernObjC::ConvertSourceLocationToLineDirective( 1674243791Sdim SourceLocation Loc, 1675243791Sdim std::string &LineString) { 1676249423Sdim if (Loc.isFileID() && GenerateLineInfo) { 1677243791Sdim LineString += "\n#line "; 1678243791Sdim PresumedLoc PLoc = SM->getPresumedLoc(Loc); 1679243791Sdim LineString += utostr(PLoc.getLine()); 1680243791Sdim LineString += " \""; 1681243791Sdim LineString += Lexer::Stringify(PLoc.getFilename()); 1682243791Sdim LineString += "\"\n"; 1683243791Sdim } 1684243791Sdim} 1685243791Sdim 1686243791Sdim/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach 1687243791Sdim/// statement to continue with its inner synthesized loop. 1688243791Sdim/// 1689243791SdimStmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) { 1690243791Sdim if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1691243791Sdim return S; 1692243791Sdim // replace continue with goto __continue_label 1693243791Sdim std::string buf; 1694243791Sdim 1695243791Sdim SourceLocation startLoc = S->getLocStart(); 1696243791Sdim buf = "goto __continue_label_"; 1697243791Sdim buf += utostr(ObjCBcLabelNo.back()); 1698243791Sdim ReplaceText(startLoc, strlen("continue"), buf); 1699243791Sdim 1700243791Sdim return 0; 1701243791Sdim} 1702243791Sdim 1703243791Sdim/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. 1704243791Sdim/// It rewrites: 1705243791Sdim/// for ( type elem in collection) { stmts; } 1706243791Sdim 1707243791Sdim/// Into: 1708243791Sdim/// { 1709243791Sdim/// type elem; 1710243791Sdim/// struct __objcFastEnumerationState enumState = { 0 }; 1711243791Sdim/// id __rw_items[16]; 1712243791Sdim/// id l_collection = (id)collection; 1713263508Sdim/// NSUInteger limit = [l_collection countByEnumeratingWithState:&enumState 1714243791Sdim/// objects:__rw_items count:16]; 1715243791Sdim/// if (limit) { 1716243791Sdim/// unsigned long startMutations = *enumState.mutationsPtr; 1717243791Sdim/// do { 1718243791Sdim/// unsigned long counter = 0; 1719243791Sdim/// do { 1720243791Sdim/// if (startMutations != *enumState.mutationsPtr) 1721243791Sdim/// objc_enumerationMutation(l_collection); 1722243791Sdim/// elem = (type)enumState.itemsPtr[counter++]; 1723243791Sdim/// stmts; 1724243791Sdim/// __continue_label: ; 1725243791Sdim/// } while (counter < limit); 1726263508Sdim/// } while ((limit = [l_collection countByEnumeratingWithState:&enumState 1727263508Sdim/// objects:__rw_items count:16])); 1728243791Sdim/// elem = nil; 1729243791Sdim/// __break_label: ; 1730243791Sdim/// } 1731243791Sdim/// else 1732243791Sdim/// elem = nil; 1733243791Sdim/// } 1734243791Sdim/// 1735243791SdimStmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 1736243791Sdim SourceLocation OrigEnd) { 1737243791Sdim assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); 1738243791Sdim assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 1739243791Sdim "ObjCForCollectionStmt Statement stack mismatch"); 1740243791Sdim assert(!ObjCBcLabelNo.empty() && 1741243791Sdim "ObjCForCollectionStmt - Label No stack empty"); 1742243791Sdim 1743243791Sdim SourceLocation startLoc = S->getLocStart(); 1744243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1745243791Sdim StringRef elementName; 1746243791Sdim std::string elementTypeAsString; 1747243791Sdim std::string buf; 1748243791Sdim // line directive first. 1749243791Sdim SourceLocation ForEachLoc = S->getForLoc(); 1750243791Sdim ConvertSourceLocationToLineDirective(ForEachLoc, buf); 1751243791Sdim buf += "{\n\t"; 1752243791Sdim if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) { 1753243791Sdim // type elem; 1754243791Sdim NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl()); 1755243791Sdim QualType ElementType = cast<ValueDecl>(D)->getType(); 1756243791Sdim if (ElementType->isObjCQualifiedIdType() || 1757243791Sdim ElementType->isObjCQualifiedInterfaceType()) 1758243791Sdim // Simply use 'id' for all qualified types. 1759243791Sdim elementTypeAsString = "id"; 1760243791Sdim else 1761243791Sdim elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy()); 1762243791Sdim buf += elementTypeAsString; 1763243791Sdim buf += " "; 1764243791Sdim elementName = D->getName(); 1765243791Sdim buf += elementName; 1766243791Sdim buf += ";\n\t"; 1767243791Sdim } 1768243791Sdim else { 1769243791Sdim DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); 1770243791Sdim elementName = DR->getDecl()->getName(); 1771243791Sdim ValueDecl *VD = cast<ValueDecl>(DR->getDecl()); 1772243791Sdim if (VD->getType()->isObjCQualifiedIdType() || 1773243791Sdim VD->getType()->isObjCQualifiedInterfaceType()) 1774243791Sdim // Simply use 'id' for all qualified types. 1775243791Sdim elementTypeAsString = "id"; 1776243791Sdim else 1777243791Sdim elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy()); 1778243791Sdim } 1779243791Sdim 1780243791Sdim // struct __objcFastEnumerationState enumState = { 0 }; 1781243791Sdim buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; 1782243791Sdim // id __rw_items[16]; 1783243791Sdim buf += "id __rw_items[16];\n\t"; 1784243791Sdim // id l_collection = (id) 1785243791Sdim buf += "id l_collection = (id)"; 1786243791Sdim // Find start location of 'collection' the hard way! 1787243791Sdim const char *startCollectionBuf = startBuf; 1788243791Sdim startCollectionBuf += 3; // skip 'for' 1789243791Sdim startCollectionBuf = strchr(startCollectionBuf, '('); 1790243791Sdim startCollectionBuf++; // skip '(' 1791243791Sdim // find 'in' and skip it. 1792243791Sdim while (*startCollectionBuf != ' ' || 1793243791Sdim *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' || 1794243791Sdim (*(startCollectionBuf+3) != ' ' && 1795243791Sdim *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) 1796243791Sdim startCollectionBuf++; 1797243791Sdim startCollectionBuf += 3; 1798243791Sdim 1799243791Sdim // Replace: "for (type element in" with string constructed thus far. 1800243791Sdim ReplaceText(startLoc, startCollectionBuf - startBuf, buf); 1801243791Sdim // Replace ')' in for '(' type elem in collection ')' with ';' 1802243791Sdim SourceLocation rightParenLoc = S->getRParenLoc(); 1803243791Sdim const char *rparenBuf = SM->getCharacterData(rightParenLoc); 1804243791Sdim SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf); 1805243791Sdim buf = ";\n\t"; 1806243791Sdim 1807243791Sdim // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 1808243791Sdim // objects:__rw_items count:16]; 1809243791Sdim // which is synthesized into: 1810263508Sdim // NSUInteger limit = 1811263508Sdim // ((NSUInteger (*) 1812263508Sdim // (id, SEL, struct __objcFastEnumerationState *, id *, NSUInteger)) 1813243791Sdim // (void *)objc_msgSend)((id)l_collection, 1814243791Sdim // sel_registerName( 1815243791Sdim // "countByEnumeratingWithState:objects:count:"), 1816243791Sdim // (struct __objcFastEnumerationState *)&state, 1817263508Sdim // (id *)__rw_items, (NSUInteger)16); 1818263508Sdim buf += "_WIN_NSUInteger limit =\n\t\t"; 1819243791Sdim SynthCountByEnumWithState(buf); 1820243791Sdim buf += ";\n\t"; 1821243791Sdim /// if (limit) { 1822243791Sdim /// unsigned long startMutations = *enumState.mutationsPtr; 1823243791Sdim /// do { 1824243791Sdim /// unsigned long counter = 0; 1825243791Sdim /// do { 1826243791Sdim /// if (startMutations != *enumState.mutationsPtr) 1827243791Sdim /// objc_enumerationMutation(l_collection); 1828243791Sdim /// elem = (type)enumState.itemsPtr[counter++]; 1829243791Sdim buf += "if (limit) {\n\t"; 1830243791Sdim buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t"; 1831243791Sdim buf += "do {\n\t\t"; 1832243791Sdim buf += "unsigned long counter = 0;\n\t\t"; 1833243791Sdim buf += "do {\n\t\t\t"; 1834243791Sdim buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t"; 1835243791Sdim buf += "objc_enumerationMutation(l_collection);\n\t\t\t"; 1836243791Sdim buf += elementName; 1837243791Sdim buf += " = ("; 1838243791Sdim buf += elementTypeAsString; 1839243791Sdim buf += ")enumState.itemsPtr[counter++];"; 1840243791Sdim // Replace ')' in for '(' type elem in collection ')' with all of these. 1841243791Sdim ReplaceText(lparenLoc, 1, buf); 1842243791Sdim 1843243791Sdim /// __continue_label: ; 1844243791Sdim /// } while (counter < limit); 1845263508Sdim /// } while ((limit = [l_collection countByEnumeratingWithState:&enumState 1846263508Sdim /// objects:__rw_items count:16])); 1847243791Sdim /// elem = nil; 1848243791Sdim /// __break_label: ; 1849243791Sdim /// } 1850243791Sdim /// else 1851243791Sdim /// elem = nil; 1852243791Sdim /// } 1853243791Sdim /// 1854243791Sdim buf = ";\n\t"; 1855243791Sdim buf += "__continue_label_"; 1856243791Sdim buf += utostr(ObjCBcLabelNo.back()); 1857243791Sdim buf += ": ;"; 1858243791Sdim buf += "\n\t\t"; 1859243791Sdim buf += "} while (counter < limit);\n\t"; 1860263508Sdim buf += "} while ((limit = "; 1861243791Sdim SynthCountByEnumWithState(buf); 1862263508Sdim buf += "));\n\t"; 1863243791Sdim buf += elementName; 1864243791Sdim buf += " = (("; 1865243791Sdim buf += elementTypeAsString; 1866243791Sdim buf += ")0);\n\t"; 1867243791Sdim buf += "__break_label_"; 1868243791Sdim buf += utostr(ObjCBcLabelNo.back()); 1869243791Sdim buf += ": ;\n\t"; 1870243791Sdim buf += "}\n\t"; 1871243791Sdim buf += "else\n\t\t"; 1872243791Sdim buf += elementName; 1873243791Sdim buf += " = (("; 1874243791Sdim buf += elementTypeAsString; 1875243791Sdim buf += ")0);\n\t"; 1876243791Sdim buf += "}\n"; 1877243791Sdim 1878243791Sdim // Insert all these *after* the statement body. 1879243791Sdim // FIXME: If this should support Obj-C++, support CXXTryStmt 1880243791Sdim if (isa<CompoundStmt>(S->getBody())) { 1881243791Sdim SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1); 1882243791Sdim InsertText(endBodyLoc, buf); 1883243791Sdim } else { 1884243791Sdim /* Need to treat single statements specially. For example: 1885243791Sdim * 1886243791Sdim * for (A *a in b) if (stuff()) break; 1887243791Sdim * for (A *a in b) xxxyy; 1888243791Sdim * 1889243791Sdim * The following code simply scans ahead to the semi to find the actual end. 1890243791Sdim */ 1891243791Sdim const char *stmtBuf = SM->getCharacterData(OrigEnd); 1892243791Sdim const char *semiBuf = strchr(stmtBuf, ';'); 1893243791Sdim assert(semiBuf && "Can't find ';'"); 1894243791Sdim SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1); 1895243791Sdim InsertText(endBodyLoc, buf); 1896243791Sdim } 1897243791Sdim Stmts.pop_back(); 1898243791Sdim ObjCBcLabelNo.pop_back(); 1899243791Sdim return 0; 1900243791Sdim} 1901243791Sdim 1902243791Sdimstatic void Write_RethrowObject(std::string &buf) { 1903243791Sdim buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n"; 1904243791Sdim buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n"; 1905243791Sdim buf += "\tid rethrow;\n"; 1906243791Sdim buf += "\t} _fin_force_rethow(_rethrow);"; 1907243791Sdim} 1908243791Sdim 1909243791Sdim/// RewriteObjCSynchronizedStmt - 1910243791Sdim/// This routine rewrites @synchronized(expr) stmt; 1911243791Sdim/// into: 1912243791Sdim/// objc_sync_enter(expr); 1913243791Sdim/// @try stmt @finally { objc_sync_exit(expr); } 1914243791Sdim/// 1915243791SdimStmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 1916243791Sdim // Get the start location and compute the semi location. 1917243791Sdim SourceLocation startLoc = S->getLocStart(); 1918243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1919243791Sdim 1920243791Sdim assert((*startBuf == '@') && "bogus @synchronized location"); 1921243791Sdim 1922243791Sdim std::string buf; 1923243791Sdim SourceLocation SynchLoc = S->getAtSynchronizedLoc(); 1924243791Sdim ConvertSourceLocationToLineDirective(SynchLoc, buf); 1925263508Sdim buf += "{ id _rethrow = 0; id _sync_obj = (id)"; 1926243791Sdim 1927243791Sdim const char *lparenBuf = startBuf; 1928243791Sdim while (*lparenBuf != '(') lparenBuf++; 1929243791Sdim ReplaceText(startLoc, lparenBuf-startBuf+1, buf); 1930243791Sdim 1931243791Sdim buf = "; objc_sync_enter(_sync_obj);\n"; 1932243791Sdim buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}"; 1933243791Sdim buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}"; 1934243791Sdim buf += "\n\tid sync_exit;"; 1935243791Sdim buf += "\n\t} _sync_exit(_sync_obj);\n"; 1936243791Sdim 1937243791Sdim // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since 1938243791Sdim // the sync expression is typically a message expression that's already 1939243791Sdim // been rewritten! (which implies the SourceLocation's are invalid). 1940243791Sdim SourceLocation RParenExprLoc = S->getSynchBody()->getLocStart(); 1941243791Sdim const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc); 1942243791Sdim while (*RParenExprLocBuf != ')') RParenExprLocBuf--; 1943243791Sdim RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf); 1944243791Sdim 1945243791Sdim SourceLocation LBranceLoc = S->getSynchBody()->getLocStart(); 1946243791Sdim const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc); 1947243791Sdim assert (*LBraceLocBuf == '{'); 1948243791Sdim ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf); 1949243791Sdim 1950243791Sdim SourceLocation startRBraceLoc = S->getSynchBody()->getLocEnd(); 1951243791Sdim assert((*SM->getCharacterData(startRBraceLoc) == '}') && 1952243791Sdim "bogus @synchronized block"); 1953243791Sdim 1954243791Sdim buf = "} catch (id e) {_rethrow = e;}\n"; 1955243791Sdim Write_RethrowObject(buf); 1956243791Sdim buf += "}\n"; 1957243791Sdim buf += "}\n"; 1958243791Sdim 1959243791Sdim ReplaceText(startRBraceLoc, 1, buf); 1960243791Sdim 1961243791Sdim return 0; 1962243791Sdim} 1963243791Sdim 1964243791Sdimvoid RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S) 1965243791Sdim{ 1966243791Sdim // Perform a bottom up traversal of all children. 1967243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 1968243791Sdim if (*CI) 1969243791Sdim WarnAboutReturnGotoStmts(*CI); 1970243791Sdim 1971243791Sdim if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) { 1972243791Sdim Diags.Report(Context->getFullLoc(S->getLocStart()), 1973243791Sdim TryFinallyContainsReturnDiag); 1974243791Sdim } 1975243791Sdim return; 1976243791Sdim} 1977243791Sdim 1978243791SdimStmt *RewriteModernObjC::RewriteObjCAutoreleasePoolStmt(ObjCAutoreleasePoolStmt *S) { 1979243791Sdim SourceLocation startLoc = S->getAtLoc(); 1980243791Sdim ReplaceText(startLoc, strlen("@autoreleasepool"), "/* @autoreleasepool */"); 1981243791Sdim ReplaceText(S->getSubStmt()->getLocStart(), 1, 1982243791Sdim "{ __AtAutoreleasePool __autoreleasepool; "); 1983243791Sdim 1984243791Sdim return 0; 1985243791Sdim} 1986243791Sdim 1987243791SdimStmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { 1988243791Sdim ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt(); 1989243791Sdim bool noCatch = S->getNumCatchStmts() == 0; 1990243791Sdim std::string buf; 1991243791Sdim SourceLocation TryLocation = S->getAtTryLoc(); 1992243791Sdim ConvertSourceLocationToLineDirective(TryLocation, buf); 1993243791Sdim 1994243791Sdim if (finalStmt) { 1995243791Sdim if (noCatch) 1996243791Sdim buf += "{ id volatile _rethrow = 0;\n"; 1997243791Sdim else { 1998243791Sdim buf += "{ id volatile _rethrow = 0;\ntry {\n"; 1999243791Sdim } 2000243791Sdim } 2001243791Sdim // Get the start location and compute the semi location. 2002243791Sdim SourceLocation startLoc = S->getLocStart(); 2003243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 2004243791Sdim 2005243791Sdim assert((*startBuf == '@') && "bogus @try location"); 2006243791Sdim if (finalStmt) 2007243791Sdim ReplaceText(startLoc, 1, buf); 2008243791Sdim else 2009243791Sdim // @try -> try 2010243791Sdim ReplaceText(startLoc, 1, ""); 2011243791Sdim 2012243791Sdim for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { 2013243791Sdim ObjCAtCatchStmt *Catch = S->getCatchStmt(I); 2014243791Sdim VarDecl *catchDecl = Catch->getCatchParamDecl(); 2015243791Sdim 2016243791Sdim startLoc = Catch->getLocStart(); 2017243791Sdim bool AtRemoved = false; 2018243791Sdim if (catchDecl) { 2019243791Sdim QualType t = catchDecl->getType(); 2020243791Sdim if (const ObjCObjectPointerType *Ptr = t->getAs<ObjCObjectPointerType>()) { 2021243791Sdim // Should be a pointer to a class. 2022243791Sdim ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface(); 2023243791Sdim if (IDecl) { 2024243791Sdim std::string Result; 2025243791Sdim ConvertSourceLocationToLineDirective(Catch->getLocStart(), Result); 2026243791Sdim 2027243791Sdim startBuf = SM->getCharacterData(startLoc); 2028243791Sdim assert((*startBuf == '@') && "bogus @catch location"); 2029243791Sdim SourceLocation rParenLoc = Catch->getRParenLoc(); 2030243791Sdim const char *rParenBuf = SM->getCharacterData(rParenLoc); 2031243791Sdim 2032243791Sdim // _objc_exc_Foo *_e as argument to catch. 2033243791Sdim Result += "catch (_objc_exc_"; Result += IDecl->getNameAsString(); 2034243791Sdim Result += " *_"; Result += catchDecl->getNameAsString(); 2035243791Sdim Result += ")"; 2036243791Sdim ReplaceText(startLoc, rParenBuf-startBuf+1, Result); 2037243791Sdim // Foo *e = (Foo *)_e; 2038243791Sdim Result.clear(); 2039243791Sdim Result = "{ "; 2040243791Sdim Result += IDecl->getNameAsString(); 2041243791Sdim Result += " *"; Result += catchDecl->getNameAsString(); 2042243791Sdim Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)"; 2043243791Sdim Result += "_"; Result += catchDecl->getNameAsString(); 2044243791Sdim 2045243791Sdim Result += "; "; 2046243791Sdim SourceLocation lBraceLoc = Catch->getCatchBody()->getLocStart(); 2047243791Sdim ReplaceText(lBraceLoc, 1, Result); 2048243791Sdim AtRemoved = true; 2049243791Sdim } 2050243791Sdim } 2051243791Sdim } 2052243791Sdim if (!AtRemoved) 2053243791Sdim // @catch -> catch 2054243791Sdim ReplaceText(startLoc, 1, ""); 2055243791Sdim 2056243791Sdim } 2057243791Sdim if (finalStmt) { 2058243791Sdim buf.clear(); 2059243791Sdim SourceLocation FinallyLoc = finalStmt->getLocStart(); 2060243791Sdim 2061243791Sdim if (noCatch) { 2062243791Sdim ConvertSourceLocationToLineDirective(FinallyLoc, buf); 2063243791Sdim buf += "catch (id e) {_rethrow = e;}\n"; 2064243791Sdim } 2065243791Sdim else { 2066243791Sdim buf += "}\n"; 2067243791Sdim ConvertSourceLocationToLineDirective(FinallyLoc, buf); 2068243791Sdim buf += "catch (id e) {_rethrow = e;}\n"; 2069243791Sdim } 2070243791Sdim 2071243791Sdim SourceLocation startFinalLoc = finalStmt->getLocStart(); 2072243791Sdim ReplaceText(startFinalLoc, 8, buf); 2073243791Sdim Stmt *body = finalStmt->getFinallyBody(); 2074243791Sdim SourceLocation startFinalBodyLoc = body->getLocStart(); 2075243791Sdim buf.clear(); 2076243791Sdim Write_RethrowObject(buf); 2077243791Sdim ReplaceText(startFinalBodyLoc, 1, buf); 2078243791Sdim 2079243791Sdim SourceLocation endFinalBodyLoc = body->getLocEnd(); 2080243791Sdim ReplaceText(endFinalBodyLoc, 1, "}\n}"); 2081243791Sdim // Now check for any return/continue/go statements within the @try. 2082243791Sdim WarnAboutReturnGotoStmts(S->getTryBody()); 2083243791Sdim } 2084243791Sdim 2085243791Sdim return 0; 2086243791Sdim} 2087243791Sdim 2088243791Sdim// This can't be done with ReplaceStmt(S, ThrowExpr), since 2089243791Sdim// the throw expression is typically a message expression that's already 2090243791Sdim// been rewritten! (which implies the SourceLocation's are invalid). 2091243791SdimStmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { 2092243791Sdim // Get the start location and compute the semi location. 2093243791Sdim SourceLocation startLoc = S->getLocStart(); 2094243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 2095243791Sdim 2096243791Sdim assert((*startBuf == '@') && "bogus @throw location"); 2097243791Sdim 2098243791Sdim std::string buf; 2099243791Sdim /* void objc_exception_throw(id) __attribute__((noreturn)); */ 2100243791Sdim if (S->getThrowExpr()) 2101243791Sdim buf = "objc_exception_throw("; 2102243791Sdim else 2103243791Sdim buf = "throw"; 2104243791Sdim 2105243791Sdim // handle "@ throw" correctly. 2106243791Sdim const char *wBuf = strchr(startBuf, 'w'); 2107243791Sdim assert((*wBuf == 'w') && "@throw: can't find 'w'"); 2108243791Sdim ReplaceText(startLoc, wBuf-startBuf+1, buf); 2109243791Sdim 2110249423Sdim SourceLocation endLoc = S->getLocEnd(); 2111249423Sdim const char *endBuf = SM->getCharacterData(endLoc); 2112249423Sdim const char *semiBuf = strchr(endBuf, ';'); 2113243791Sdim assert((*semiBuf == ';') && "@throw: can't find ';'"); 2114243791Sdim SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf); 2115243791Sdim if (S->getThrowExpr()) 2116243791Sdim ReplaceText(semiLoc, 1, ");"); 2117243791Sdim return 0; 2118243791Sdim} 2119243791Sdim 2120243791SdimStmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { 2121243791Sdim // Create a new string expression. 2122243791Sdim QualType StrType = Context->getPointerType(Context->CharTy); 2123243791Sdim std::string StrEncoding; 2124243791Sdim Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); 2125243791Sdim Expr *Replacement = StringLiteral::Create(*Context, StrEncoding, 2126243791Sdim StringLiteral::Ascii, false, 2127243791Sdim StrType, SourceLocation()); 2128243791Sdim ReplaceStmt(Exp, Replacement); 2129243791Sdim 2130243791Sdim // Replace this subexpr in the parent. 2131243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2132243791Sdim return Replacement; 2133243791Sdim} 2134243791Sdim 2135243791SdimStmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { 2136243791Sdim if (!SelGetUidFunctionDecl) 2137243791Sdim SynthSelGetUidFunctionDecl(); 2138243791Sdim assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl"); 2139243791Sdim // Create a call to sel_registerName("selName"). 2140243791Sdim SmallVector<Expr*, 8> SelExprs; 2141243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2142243791Sdim SelExprs.push_back(StringLiteral::Create(*Context, 2143243791Sdim Exp->getSelector().getAsString(), 2144243791Sdim StringLiteral::Ascii, false, 2145243791Sdim argType, SourceLocation())); 2146243791Sdim CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 2147243791Sdim &SelExprs[0], SelExprs.size()); 2148243791Sdim ReplaceStmt(Exp, SelExp); 2149243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2150243791Sdim return SelExp; 2151243791Sdim} 2152243791Sdim 2153243791SdimCallExpr *RewriteModernObjC::SynthesizeCallToFunctionDecl( 2154243791Sdim FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc, 2155243791Sdim SourceLocation EndLoc) { 2156243791Sdim // Get the type, we will need to reference it in a couple spots. 2157243791Sdim QualType msgSendType = FD->getType(); 2158243791Sdim 2159243791Sdim // Create a reference to the objc_msgSend() declaration. 2160243791Sdim DeclRefExpr *DRE = 2161243791Sdim new (Context) DeclRefExpr(FD, false, msgSendType, VK_LValue, SourceLocation()); 2162243791Sdim 2163243791Sdim // Now, we cast the reference to a pointer to the objc_msgSend type. 2164243791Sdim QualType pToFunc = Context->getPointerType(msgSendType); 2165243791Sdim ImplicitCastExpr *ICE = 2166243791Sdim ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, 2167243791Sdim DRE, 0, VK_RValue); 2168243791Sdim 2169243791Sdim const FunctionType *FT = msgSendType->getAs<FunctionType>(); 2170243791Sdim 2171243791Sdim CallExpr *Exp = 2172243791Sdim new (Context) CallExpr(*Context, ICE, llvm::makeArrayRef(args, nargs), 2173243791Sdim FT->getCallResultType(*Context), 2174243791Sdim VK_RValue, EndLoc); 2175243791Sdim return Exp; 2176243791Sdim} 2177243791Sdim 2178243791Sdimstatic bool scanForProtocolRefs(const char *startBuf, const char *endBuf, 2179243791Sdim const char *&startRef, const char *&endRef) { 2180243791Sdim while (startBuf < endBuf) { 2181243791Sdim if (*startBuf == '<') 2182243791Sdim startRef = startBuf; // mark the start. 2183243791Sdim if (*startBuf == '>') { 2184243791Sdim if (startRef && *startRef == '<') { 2185243791Sdim endRef = startBuf; // mark the end. 2186243791Sdim return true; 2187243791Sdim } 2188243791Sdim return false; 2189243791Sdim } 2190243791Sdim startBuf++; 2191243791Sdim } 2192243791Sdim return false; 2193243791Sdim} 2194243791Sdim 2195243791Sdimstatic void scanToNextArgument(const char *&argRef) { 2196243791Sdim int angle = 0; 2197243791Sdim while (*argRef != ')' && (*argRef != ',' || angle > 0)) { 2198243791Sdim if (*argRef == '<') 2199243791Sdim angle++; 2200243791Sdim else if (*argRef == '>') 2201243791Sdim angle--; 2202243791Sdim argRef++; 2203243791Sdim } 2204243791Sdim assert(angle == 0 && "scanToNextArgument - bad protocol type syntax"); 2205243791Sdim} 2206243791Sdim 2207243791Sdimbool RewriteModernObjC::needToScanForQualifiers(QualType T) { 2208243791Sdim if (T->isObjCQualifiedIdType()) 2209243791Sdim return true; 2210243791Sdim if (const PointerType *PT = T->getAs<PointerType>()) { 2211243791Sdim if (PT->getPointeeType()->isObjCQualifiedIdType()) 2212243791Sdim return true; 2213243791Sdim } 2214243791Sdim if (T->isObjCObjectPointerType()) { 2215243791Sdim T = T->getPointeeType(); 2216243791Sdim return T->isObjCQualifiedInterfaceType(); 2217243791Sdim } 2218243791Sdim if (T->isArrayType()) { 2219243791Sdim QualType ElemTy = Context->getBaseElementType(T); 2220243791Sdim return needToScanForQualifiers(ElemTy); 2221243791Sdim } 2222243791Sdim return false; 2223243791Sdim} 2224243791Sdim 2225243791Sdimvoid RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { 2226243791Sdim QualType Type = E->getType(); 2227243791Sdim if (needToScanForQualifiers(Type)) { 2228243791Sdim SourceLocation Loc, EndLoc; 2229243791Sdim 2230243791Sdim if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { 2231243791Sdim Loc = ECE->getLParenLoc(); 2232243791Sdim EndLoc = ECE->getRParenLoc(); 2233243791Sdim } else { 2234243791Sdim Loc = E->getLocStart(); 2235243791Sdim EndLoc = E->getLocEnd(); 2236243791Sdim } 2237243791Sdim // This will defend against trying to rewrite synthesized expressions. 2238243791Sdim if (Loc.isInvalid() || EndLoc.isInvalid()) 2239243791Sdim return; 2240243791Sdim 2241243791Sdim const char *startBuf = SM->getCharacterData(Loc); 2242243791Sdim const char *endBuf = SM->getCharacterData(EndLoc); 2243243791Sdim const char *startRef = 0, *endRef = 0; 2244243791Sdim if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2245243791Sdim // Get the locations of the startRef, endRef. 2246243791Sdim SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf); 2247243791Sdim SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1); 2248243791Sdim // Comment out the protocol references. 2249243791Sdim InsertText(LessLoc, "/*"); 2250243791Sdim InsertText(GreaterLoc, "*/"); 2251243791Sdim } 2252243791Sdim } 2253243791Sdim} 2254243791Sdim 2255243791Sdimvoid RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { 2256243791Sdim SourceLocation Loc; 2257243791Sdim QualType Type; 2258243791Sdim const FunctionProtoType *proto = 0; 2259243791Sdim if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) { 2260243791Sdim Loc = VD->getLocation(); 2261243791Sdim Type = VD->getType(); 2262243791Sdim } 2263243791Sdim else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) { 2264243791Sdim Loc = FD->getLocation(); 2265243791Sdim // Check for ObjC 'id' and class types that have been adorned with protocol 2266243791Sdim // information (id<p>, C<p>*). The protocol references need to be rewritten! 2267243791Sdim const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 2268243791Sdim assert(funcType && "missing function type"); 2269243791Sdim proto = dyn_cast<FunctionProtoType>(funcType); 2270243791Sdim if (!proto) 2271243791Sdim return; 2272243791Sdim Type = proto->getResultType(); 2273243791Sdim } 2274243791Sdim else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) { 2275243791Sdim Loc = FD->getLocation(); 2276243791Sdim Type = FD->getType(); 2277243791Sdim } 2278249423Sdim else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(Dcl)) { 2279249423Sdim Loc = TD->getLocation(); 2280249423Sdim Type = TD->getUnderlyingType(); 2281249423Sdim } 2282243791Sdim else 2283243791Sdim return; 2284243791Sdim 2285243791Sdim if (needToScanForQualifiers(Type)) { 2286243791Sdim // Since types are unique, we need to scan the buffer. 2287243791Sdim 2288243791Sdim const char *endBuf = SM->getCharacterData(Loc); 2289243791Sdim const char *startBuf = endBuf; 2290243791Sdim while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) 2291243791Sdim startBuf--; // scan backward (from the decl location) for return type. 2292243791Sdim const char *startRef = 0, *endRef = 0; 2293243791Sdim if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2294243791Sdim // Get the locations of the startRef, endRef. 2295243791Sdim SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf); 2296243791Sdim SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1); 2297243791Sdim // Comment out the protocol references. 2298243791Sdim InsertText(LessLoc, "/*"); 2299243791Sdim InsertText(GreaterLoc, "*/"); 2300243791Sdim } 2301243791Sdim } 2302243791Sdim if (!proto) 2303243791Sdim return; // most likely, was a variable 2304243791Sdim // Now check arguments. 2305243791Sdim const char *startBuf = SM->getCharacterData(Loc); 2306243791Sdim const char *startFuncBuf = startBuf; 2307243791Sdim for (unsigned i = 0; i < proto->getNumArgs(); i++) { 2308243791Sdim if (needToScanForQualifiers(proto->getArgType(i))) { 2309243791Sdim // Since types are unique, we need to scan the buffer. 2310243791Sdim 2311243791Sdim const char *endBuf = startBuf; 2312243791Sdim // scan forward (from the decl location) for argument types. 2313243791Sdim scanToNextArgument(endBuf); 2314243791Sdim const char *startRef = 0, *endRef = 0; 2315243791Sdim if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2316243791Sdim // Get the locations of the startRef, endRef. 2317243791Sdim SourceLocation LessLoc = 2318243791Sdim Loc.getLocWithOffset(startRef-startFuncBuf); 2319243791Sdim SourceLocation GreaterLoc = 2320243791Sdim Loc.getLocWithOffset(endRef-startFuncBuf+1); 2321243791Sdim // Comment out the protocol references. 2322243791Sdim InsertText(LessLoc, "/*"); 2323243791Sdim InsertText(GreaterLoc, "*/"); 2324243791Sdim } 2325243791Sdim startBuf = ++endBuf; 2326243791Sdim } 2327243791Sdim else { 2328243791Sdim // If the function name is derived from a macro expansion, then the 2329243791Sdim // argument buffer will not follow the name. Need to speak with Chris. 2330243791Sdim while (*startBuf && *startBuf != ')' && *startBuf != ',') 2331243791Sdim startBuf++; // scan forward (from the decl location) for argument types. 2332243791Sdim startBuf++; 2333243791Sdim } 2334243791Sdim } 2335243791Sdim} 2336243791Sdim 2337243791Sdimvoid RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) { 2338243791Sdim QualType QT = ND->getType(); 2339243791Sdim const Type* TypePtr = QT->getAs<Type>(); 2340243791Sdim if (!isa<TypeOfExprType>(TypePtr)) 2341243791Sdim return; 2342243791Sdim while (isa<TypeOfExprType>(TypePtr)) { 2343243791Sdim const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 2344243791Sdim QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 2345243791Sdim TypePtr = QT->getAs<Type>(); 2346243791Sdim } 2347243791Sdim // FIXME. This will not work for multiple declarators; as in: 2348243791Sdim // __typeof__(a) b,c,d; 2349243791Sdim std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy())); 2350243791Sdim SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 2351243791Sdim const char *startBuf = SM->getCharacterData(DeclLoc); 2352243791Sdim if (ND->getInit()) { 2353243791Sdim std::string Name(ND->getNameAsString()); 2354243791Sdim TypeAsString += " " + Name + " = "; 2355243791Sdim Expr *E = ND->getInit(); 2356243791Sdim SourceLocation startLoc; 2357243791Sdim if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 2358243791Sdim startLoc = ECE->getLParenLoc(); 2359243791Sdim else 2360243791Sdim startLoc = E->getLocStart(); 2361243791Sdim startLoc = SM->getExpansionLoc(startLoc); 2362243791Sdim const char *endBuf = SM->getCharacterData(startLoc); 2363243791Sdim ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 2364243791Sdim } 2365243791Sdim else { 2366243791Sdim SourceLocation X = ND->getLocEnd(); 2367243791Sdim X = SM->getExpansionLoc(X); 2368243791Sdim const char *endBuf = SM->getCharacterData(X); 2369243791Sdim ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 2370243791Sdim } 2371243791Sdim} 2372243791Sdim 2373243791Sdim// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); 2374243791Sdimvoid RewriteModernObjC::SynthSelGetUidFunctionDecl() { 2375243791Sdim IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); 2376243791Sdim SmallVector<QualType, 16> ArgTys; 2377243791Sdim ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2378243791Sdim QualType getFuncType = 2379249423Sdim getSimpleFunctionType(Context->getObjCSelType(), ArgTys); 2380243791Sdim SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2381249423Sdim SourceLocation(), 2382249423Sdim SourceLocation(), 2383249423Sdim SelGetUidIdent, getFuncType, 0, 2384249423Sdim SC_Extern); 2385243791Sdim} 2386243791Sdim 2387243791Sdimvoid RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) { 2388243791Sdim // declared in <objc/objc.h> 2389243791Sdim if (FD->getIdentifier() && 2390243791Sdim FD->getName() == "sel_registerName") { 2391243791Sdim SelGetUidFunctionDecl = FD; 2392243791Sdim return; 2393243791Sdim } 2394243791Sdim RewriteObjCQualifiedInterfaceTypes(FD); 2395243791Sdim} 2396243791Sdim 2397243791Sdimvoid RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) { 2398243791Sdim std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 2399243791Sdim const char *argPtr = TypeString.c_str(); 2400243791Sdim if (!strchr(argPtr, '^')) { 2401243791Sdim Str += TypeString; 2402243791Sdim return; 2403243791Sdim } 2404243791Sdim while (*argPtr) { 2405243791Sdim Str += (*argPtr == '^' ? '*' : *argPtr); 2406243791Sdim argPtr++; 2407243791Sdim } 2408243791Sdim} 2409243791Sdim 2410243791Sdim// FIXME. Consolidate this routine with RewriteBlockPointerType. 2411243791Sdimvoid RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str, 2412243791Sdim ValueDecl *VD) { 2413243791Sdim QualType Type = VD->getType(); 2414243791Sdim std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 2415243791Sdim const char *argPtr = TypeString.c_str(); 2416243791Sdim int paren = 0; 2417243791Sdim while (*argPtr) { 2418243791Sdim switch (*argPtr) { 2419243791Sdim case '(': 2420243791Sdim Str += *argPtr; 2421243791Sdim paren++; 2422243791Sdim break; 2423243791Sdim case ')': 2424243791Sdim Str += *argPtr; 2425243791Sdim paren--; 2426243791Sdim break; 2427243791Sdim case '^': 2428243791Sdim Str += '*'; 2429243791Sdim if (paren == 1) 2430243791Sdim Str += VD->getNameAsString(); 2431243791Sdim break; 2432243791Sdim default: 2433243791Sdim Str += *argPtr; 2434243791Sdim break; 2435243791Sdim } 2436243791Sdim argPtr++; 2437243791Sdim } 2438243791Sdim} 2439243791Sdim 2440243791Sdimvoid RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { 2441243791Sdim SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 2442243791Sdim const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 2443243791Sdim const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType); 2444243791Sdim if (!proto) 2445243791Sdim return; 2446243791Sdim QualType Type = proto->getResultType(); 2447243791Sdim std::string FdStr = Type.getAsString(Context->getPrintingPolicy()); 2448243791Sdim FdStr += " "; 2449243791Sdim FdStr += FD->getName(); 2450243791Sdim FdStr += "("; 2451243791Sdim unsigned numArgs = proto->getNumArgs(); 2452243791Sdim for (unsigned i = 0; i < numArgs; i++) { 2453243791Sdim QualType ArgType = proto->getArgType(i); 2454243791Sdim RewriteBlockPointerType(FdStr, ArgType); 2455243791Sdim if (i+1 < numArgs) 2456243791Sdim FdStr += ", "; 2457243791Sdim } 2458243791Sdim if (FD->isVariadic()) { 2459243791Sdim FdStr += (numArgs > 0) ? ", ...);\n" : "...);\n"; 2460243791Sdim } 2461243791Sdim else 2462243791Sdim FdStr += ");\n"; 2463243791Sdim InsertText(FunLocStart, FdStr); 2464243791Sdim} 2465243791Sdim 2466263508Sdim// SynthSuperConstructorFunctionDecl - id __rw_objc_super(id obj, id super); 2467263508Sdimvoid RewriteModernObjC::SynthSuperConstructorFunctionDecl() { 2468263508Sdim if (SuperConstructorFunctionDecl) 2469243791Sdim return; 2470243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super"); 2471243791Sdim SmallVector<QualType, 16> ArgTys; 2472243791Sdim QualType argT = Context->getObjCIdType(); 2473243791Sdim assert(!argT.isNull() && "Can't find 'id' type"); 2474243791Sdim ArgTys.push_back(argT); 2475243791Sdim ArgTys.push_back(argT); 2476243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2477249423Sdim ArgTys); 2478263508Sdim SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2479249423Sdim SourceLocation(), 2480249423Sdim SourceLocation(), 2481249423Sdim msgSendIdent, msgSendType, 2482249423Sdim 0, SC_Extern); 2483243791Sdim} 2484243791Sdim 2485243791Sdim// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); 2486243791Sdimvoid RewriteModernObjC::SynthMsgSendFunctionDecl() { 2487243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend"); 2488243791Sdim SmallVector<QualType, 16> ArgTys; 2489243791Sdim QualType argT = Context->getObjCIdType(); 2490243791Sdim assert(!argT.isNull() && "Can't find 'id' type"); 2491243791Sdim ArgTys.push_back(argT); 2492243791Sdim argT = Context->getObjCSelType(); 2493243791Sdim assert(!argT.isNull() && "Can't find 'SEL' type"); 2494243791Sdim ArgTys.push_back(argT); 2495243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2496249423Sdim ArgTys, /*isVariadic=*/true); 2497243791Sdim MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2498249423Sdim SourceLocation(), 2499249423Sdim SourceLocation(), 2500249423Sdim msgSendIdent, msgSendType, 0, 2501249423Sdim SC_Extern); 2502243791Sdim} 2503243791Sdim 2504243791Sdim// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void); 2505243791Sdimvoid RewriteModernObjC::SynthMsgSendSuperFunctionDecl() { 2506243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); 2507243791Sdim SmallVector<QualType, 2> ArgTys; 2508243791Sdim ArgTys.push_back(Context->VoidTy); 2509243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2510249423Sdim ArgTys, /*isVariadic=*/true); 2511243791Sdim MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2512249423Sdim SourceLocation(), 2513249423Sdim SourceLocation(), 2514249423Sdim msgSendIdent, msgSendType, 0, 2515249423Sdim SC_Extern); 2516243791Sdim} 2517243791Sdim 2518243791Sdim// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); 2519243791Sdimvoid RewriteModernObjC::SynthMsgSendStretFunctionDecl() { 2520243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret"); 2521243791Sdim SmallVector<QualType, 16> ArgTys; 2522243791Sdim QualType argT = Context->getObjCIdType(); 2523243791Sdim assert(!argT.isNull() && "Can't find 'id' type"); 2524243791Sdim ArgTys.push_back(argT); 2525243791Sdim argT = Context->getObjCSelType(); 2526243791Sdim assert(!argT.isNull() && "Can't find 'SEL' type"); 2527243791Sdim ArgTys.push_back(argT); 2528243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2529249423Sdim ArgTys, /*isVariadic=*/true); 2530243791Sdim MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2531249423Sdim SourceLocation(), 2532249423Sdim SourceLocation(), 2533249423Sdim msgSendIdent, msgSendType, 0, 2534249423Sdim SC_Extern); 2535243791Sdim} 2536243791Sdim 2537243791Sdim// SynthMsgSendSuperStretFunctionDecl - 2538243791Sdim// id objc_msgSendSuper_stret(void); 2539243791Sdimvoid RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() { 2540243791Sdim IdentifierInfo *msgSendIdent = 2541243791Sdim &Context->Idents.get("objc_msgSendSuper_stret"); 2542243791Sdim SmallVector<QualType, 2> ArgTys; 2543243791Sdim ArgTys.push_back(Context->VoidTy); 2544243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2545249423Sdim ArgTys, /*isVariadic=*/true); 2546243791Sdim MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2547243791Sdim SourceLocation(), 2548243791Sdim SourceLocation(), 2549249423Sdim msgSendIdent, 2550249423Sdim msgSendType, 0, 2551249423Sdim SC_Extern); 2552243791Sdim} 2553243791Sdim 2554243791Sdim// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); 2555243791Sdimvoid RewriteModernObjC::SynthMsgSendFpretFunctionDecl() { 2556243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret"); 2557243791Sdim SmallVector<QualType, 16> ArgTys; 2558243791Sdim QualType argT = Context->getObjCIdType(); 2559243791Sdim assert(!argT.isNull() && "Can't find 'id' type"); 2560243791Sdim ArgTys.push_back(argT); 2561243791Sdim argT = Context->getObjCSelType(); 2562243791Sdim assert(!argT.isNull() && "Can't find 'SEL' type"); 2563243791Sdim ArgTys.push_back(argT); 2564243791Sdim QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, 2565249423Sdim ArgTys, /*isVariadic=*/true); 2566243791Sdim MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2567249423Sdim SourceLocation(), 2568249423Sdim SourceLocation(), 2569249423Sdim msgSendIdent, msgSendType, 0, 2570249423Sdim SC_Extern); 2571243791Sdim} 2572243791Sdim 2573243791Sdim// SynthGetClassFunctionDecl - Class objc_getClass(const char *name); 2574243791Sdimvoid RewriteModernObjC::SynthGetClassFunctionDecl() { 2575243791Sdim IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); 2576243791Sdim SmallVector<QualType, 16> ArgTys; 2577243791Sdim ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2578243791Sdim QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 2579249423Sdim ArgTys); 2580243791Sdim GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2581249423Sdim SourceLocation(), 2582249423Sdim SourceLocation(), 2583249423Sdim getClassIdent, getClassType, 0, 2584249423Sdim SC_Extern); 2585243791Sdim} 2586243791Sdim 2587243791Sdim// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); 2588243791Sdimvoid RewriteModernObjC::SynthGetSuperClassFunctionDecl() { 2589243791Sdim IdentifierInfo *getSuperClassIdent = 2590243791Sdim &Context->Idents.get("class_getSuperclass"); 2591243791Sdim SmallVector<QualType, 16> ArgTys; 2592243791Sdim ArgTys.push_back(Context->getObjCClassType()); 2593243791Sdim QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 2594249423Sdim ArgTys); 2595243791Sdim GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2596243791Sdim SourceLocation(), 2597243791Sdim SourceLocation(), 2598243791Sdim getSuperClassIdent, 2599243791Sdim getClassType, 0, 2600249423Sdim SC_Extern); 2601243791Sdim} 2602243791Sdim 2603243791Sdim// SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name); 2604243791Sdimvoid RewriteModernObjC::SynthGetMetaClassFunctionDecl() { 2605243791Sdim IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); 2606243791Sdim SmallVector<QualType, 16> ArgTys; 2607243791Sdim ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2608243791Sdim QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 2609249423Sdim ArgTys); 2610243791Sdim GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2611249423Sdim SourceLocation(), 2612249423Sdim SourceLocation(), 2613249423Sdim getClassIdent, getClassType, 2614249423Sdim 0, SC_Extern); 2615243791Sdim} 2616243791Sdim 2617243791SdimStmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { 2618243791Sdim QualType strType = getConstantStringStructType(); 2619243791Sdim 2620243791Sdim std::string S = "__NSConstantStringImpl_"; 2621243791Sdim 2622243791Sdim std::string tmpName = InFileName; 2623243791Sdim unsigned i; 2624243791Sdim for (i=0; i < tmpName.length(); i++) { 2625243791Sdim char c = tmpName.at(i); 2626243791Sdim // replace any non alphanumeric characters with '_'. 2627249423Sdim if (!isAlphanumeric(c)) 2628243791Sdim tmpName[i] = '_'; 2629243791Sdim } 2630243791Sdim S += tmpName; 2631243791Sdim S += "_"; 2632243791Sdim S += utostr(NumObjCStringLiterals++); 2633243791Sdim 2634243791Sdim Preamble += "static __NSConstantStringImpl " + S; 2635243791Sdim Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,"; 2636243791Sdim Preamble += "0x000007c8,"; // utf8_str 2637243791Sdim // The pretty printer for StringLiteral handles escape characters properly. 2638243791Sdim std::string prettyBufS; 2639243791Sdim llvm::raw_string_ostream prettyBuf(prettyBufS); 2640243791Sdim Exp->getString()->printPretty(prettyBuf, 0, PrintingPolicy(LangOpts)); 2641243791Sdim Preamble += prettyBuf.str(); 2642243791Sdim Preamble += ","; 2643243791Sdim Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; 2644243791Sdim 2645243791Sdim VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 2646243791Sdim SourceLocation(), &Context->Idents.get(S), 2647249423Sdim strType, 0, SC_Static); 2648243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue, 2649243791Sdim SourceLocation()); 2650243791Sdim Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, 2651243791Sdim Context->getPointerType(DRE->getType()), 2652243791Sdim VK_RValue, OK_Ordinary, 2653243791Sdim SourceLocation()); 2654243791Sdim // cast to NSConstantString * 2655243791Sdim CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), 2656243791Sdim CK_CPointerToObjCPointerCast, Unop); 2657243791Sdim ReplaceStmt(Exp, cast); 2658243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2659243791Sdim return cast; 2660243791Sdim} 2661243791Sdim 2662243791SdimStmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) { 2663243791Sdim unsigned IntSize = 2664243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 2665243791Sdim 2666243791Sdim Expr *FlagExp = IntegerLiteral::Create(*Context, 2667243791Sdim llvm::APInt(IntSize, Exp->getValue()), 2668243791Sdim Context->IntTy, Exp->getLocation()); 2669243791Sdim CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy, 2670243791Sdim CK_BitCast, FlagExp); 2671243791Sdim ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(), 2672243791Sdim cast); 2673243791Sdim ReplaceStmt(Exp, PE); 2674243791Sdim return PE; 2675243791Sdim} 2676243791Sdim 2677243791SdimStmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) { 2678243791Sdim // synthesize declaration of helper functions needed in this routine. 2679243791Sdim if (!SelGetUidFunctionDecl) 2680243791Sdim SynthSelGetUidFunctionDecl(); 2681243791Sdim // use objc_msgSend() for all. 2682243791Sdim if (!MsgSendFunctionDecl) 2683243791Sdim SynthMsgSendFunctionDecl(); 2684243791Sdim if (!GetClassFunctionDecl) 2685243791Sdim SynthGetClassFunctionDecl(); 2686243791Sdim 2687243791Sdim FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 2688243791Sdim SourceLocation StartLoc = Exp->getLocStart(); 2689243791Sdim SourceLocation EndLoc = Exp->getLocEnd(); 2690243791Sdim 2691243791Sdim // Synthesize a call to objc_msgSend(). 2692243791Sdim SmallVector<Expr*, 4> MsgExprs; 2693243791Sdim SmallVector<Expr*, 4> ClsExprs; 2694243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2695243791Sdim 2696243791Sdim // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument. 2697243791Sdim ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod(); 2698243791Sdim ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface(); 2699243791Sdim 2700243791Sdim IdentifierInfo *clsName = BoxingClass->getIdentifier(); 2701243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 2702243791Sdim clsName->getName(), 2703243791Sdim StringLiteral::Ascii, false, 2704243791Sdim argType, SourceLocation())); 2705243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 2706243791Sdim &ClsExprs[0], 2707243791Sdim ClsExprs.size(), 2708243791Sdim StartLoc, EndLoc); 2709243791Sdim MsgExprs.push_back(Cls); 2710243791Sdim 2711243791Sdim // Create a call to sel_registerName("<BoxingMethod>:"), etc. 2712243791Sdim // it will be the 2nd argument. 2713243791Sdim SmallVector<Expr*, 4> SelExprs; 2714243791Sdim SelExprs.push_back(StringLiteral::Create(*Context, 2715243791Sdim BoxingMethod->getSelector().getAsString(), 2716243791Sdim StringLiteral::Ascii, false, 2717243791Sdim argType, SourceLocation())); 2718243791Sdim CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 2719243791Sdim &SelExprs[0], SelExprs.size(), 2720243791Sdim StartLoc, EndLoc); 2721243791Sdim MsgExprs.push_back(SelExp); 2722243791Sdim 2723243791Sdim // User provided sub-expression is the 3rd, and last, argument. 2724243791Sdim Expr *subExpr = Exp->getSubExpr(); 2725243791Sdim if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) { 2726243791Sdim QualType type = ICE->getType(); 2727243791Sdim const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 2728243791Sdim CastKind CK = CK_BitCast; 2729243791Sdim if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType()) 2730243791Sdim CK = CK_IntegralToBoolean; 2731243791Sdim subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr); 2732243791Sdim } 2733243791Sdim MsgExprs.push_back(subExpr); 2734243791Sdim 2735243791Sdim SmallVector<QualType, 4> ArgTypes; 2736243791Sdim ArgTypes.push_back(Context->getObjCIdType()); 2737243791Sdim ArgTypes.push_back(Context->getObjCSelType()); 2738243791Sdim for (ObjCMethodDecl::param_iterator PI = BoxingMethod->param_begin(), 2739243791Sdim E = BoxingMethod->param_end(); PI != E; ++PI) 2740243791Sdim ArgTypes.push_back((*PI)->getType()); 2741243791Sdim 2742243791Sdim QualType returnType = Exp->getType(); 2743243791Sdim // Get the type, we will need to reference it in a couple spots. 2744243791Sdim QualType msgSendType = MsgSendFlavor->getType(); 2745243791Sdim 2746243791Sdim // Create a reference to the objc_msgSend() declaration. 2747243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 2748243791Sdim VK_LValue, SourceLocation()); 2749243791Sdim 2750243791Sdim CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, 2751243791Sdim Context->getPointerType(Context->VoidTy), 2752243791Sdim CK_BitCast, DRE); 2753243791Sdim 2754243791Sdim // Now do the "normal" pointer to function cast. 2755243791Sdim QualType castType = 2756249423Sdim getSimpleFunctionType(returnType, ArgTypes, BoxingMethod->isVariadic()); 2757243791Sdim castType = Context->getPointerType(castType); 2758243791Sdim cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 2759243791Sdim cast); 2760243791Sdim 2761243791Sdim // Don't forget the parens to enforce the proper binding. 2762243791Sdim ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 2763243791Sdim 2764243791Sdim const FunctionType *FT = msgSendType->getAs<FunctionType>(); 2765243791Sdim CallExpr *CE = new (Context) CallExpr(*Context, PE, MsgExprs, 2766243791Sdim FT->getResultType(), VK_RValue, 2767243791Sdim EndLoc); 2768243791Sdim ReplaceStmt(Exp, CE); 2769243791Sdim return CE; 2770243791Sdim} 2771243791Sdim 2772243791SdimStmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { 2773243791Sdim // synthesize declaration of helper functions needed in this routine. 2774243791Sdim if (!SelGetUidFunctionDecl) 2775243791Sdim SynthSelGetUidFunctionDecl(); 2776243791Sdim // use objc_msgSend() for all. 2777243791Sdim if (!MsgSendFunctionDecl) 2778243791Sdim SynthMsgSendFunctionDecl(); 2779243791Sdim if (!GetClassFunctionDecl) 2780243791Sdim SynthGetClassFunctionDecl(); 2781243791Sdim 2782243791Sdim FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 2783243791Sdim SourceLocation StartLoc = Exp->getLocStart(); 2784243791Sdim SourceLocation EndLoc = Exp->getLocEnd(); 2785243791Sdim 2786243791Sdim // Build the expression: __NSContainer_literal(int, ...).arr 2787243791Sdim QualType IntQT = Context->IntTy; 2788243791Sdim QualType NSArrayFType = 2789249423Sdim getSimpleFunctionType(Context->VoidTy, IntQT, true); 2790243791Sdim std::string NSArrayFName("__NSContainer_literal"); 2791243791Sdim FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName); 2792243791Sdim DeclRefExpr *NSArrayDRE = 2793243791Sdim new (Context) DeclRefExpr(NSArrayFD, false, NSArrayFType, VK_RValue, 2794243791Sdim SourceLocation()); 2795243791Sdim 2796243791Sdim SmallVector<Expr*, 16> InitExprs; 2797243791Sdim unsigned NumElements = Exp->getNumElements(); 2798243791Sdim unsigned UnsignedIntSize = 2799243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 2800243791Sdim Expr *count = IntegerLiteral::Create(*Context, 2801243791Sdim llvm::APInt(UnsignedIntSize, NumElements), 2802243791Sdim Context->UnsignedIntTy, SourceLocation()); 2803243791Sdim InitExprs.push_back(count); 2804243791Sdim for (unsigned i = 0; i < NumElements; i++) 2805243791Sdim InitExprs.push_back(Exp->getElement(i)); 2806243791Sdim Expr *NSArrayCallExpr = 2807243791Sdim new (Context) CallExpr(*Context, NSArrayDRE, InitExprs, 2808243791Sdim NSArrayFType, VK_LValue, SourceLocation()); 2809243791Sdim 2810243791Sdim FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(), 2811243791Sdim SourceLocation(), 2812243791Sdim &Context->Idents.get("arr"), 2813243791Sdim Context->getPointerType(Context->VoidPtrTy), 0, 2814243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 2815243791Sdim ICIS_NoInit); 2816243791Sdim MemberExpr *ArrayLiteralME = 2817243791Sdim new (Context) MemberExpr(NSArrayCallExpr, false, ARRFD, 2818243791Sdim SourceLocation(), 2819243791Sdim ARRFD->getType(), VK_LValue, 2820243791Sdim OK_Ordinary); 2821243791Sdim QualType ConstIdT = Context->getObjCIdType().withConst(); 2822243791Sdim CStyleCastExpr * ArrayLiteralObjects = 2823243791Sdim NoTypeInfoCStyleCastExpr(Context, 2824243791Sdim Context->getPointerType(ConstIdT), 2825243791Sdim CK_BitCast, 2826243791Sdim ArrayLiteralME); 2827243791Sdim 2828243791Sdim // Synthesize a call to objc_msgSend(). 2829243791Sdim SmallVector<Expr*, 32> MsgExprs; 2830243791Sdim SmallVector<Expr*, 4> ClsExprs; 2831243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2832243791Sdim QualType expType = Exp->getType(); 2833243791Sdim 2834243791Sdim // Create a call to objc_getClass("NSArray"). It will be th 1st argument. 2835243791Sdim ObjCInterfaceDecl *Class = 2836243791Sdim expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface(); 2837243791Sdim 2838243791Sdim IdentifierInfo *clsName = Class->getIdentifier(); 2839243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 2840243791Sdim clsName->getName(), 2841243791Sdim StringLiteral::Ascii, false, 2842243791Sdim argType, SourceLocation())); 2843243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 2844243791Sdim &ClsExprs[0], 2845243791Sdim ClsExprs.size(), 2846243791Sdim StartLoc, EndLoc); 2847243791Sdim MsgExprs.push_back(Cls); 2848243791Sdim 2849243791Sdim // Create a call to sel_registerName("arrayWithObjects:count:"). 2850243791Sdim // it will be the 2nd argument. 2851243791Sdim SmallVector<Expr*, 4> SelExprs; 2852243791Sdim ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod(); 2853243791Sdim SelExprs.push_back(StringLiteral::Create(*Context, 2854243791Sdim ArrayMethod->getSelector().getAsString(), 2855243791Sdim StringLiteral::Ascii, false, 2856243791Sdim argType, SourceLocation())); 2857243791Sdim CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 2858243791Sdim &SelExprs[0], SelExprs.size(), 2859243791Sdim StartLoc, EndLoc); 2860243791Sdim MsgExprs.push_back(SelExp); 2861243791Sdim 2862243791Sdim // (const id [])objects 2863243791Sdim MsgExprs.push_back(ArrayLiteralObjects); 2864243791Sdim 2865243791Sdim // (NSUInteger)cnt 2866243791Sdim Expr *cnt = IntegerLiteral::Create(*Context, 2867243791Sdim llvm::APInt(UnsignedIntSize, NumElements), 2868243791Sdim Context->UnsignedIntTy, SourceLocation()); 2869243791Sdim MsgExprs.push_back(cnt); 2870243791Sdim 2871243791Sdim 2872243791Sdim SmallVector<QualType, 4> ArgTypes; 2873243791Sdim ArgTypes.push_back(Context->getObjCIdType()); 2874243791Sdim ArgTypes.push_back(Context->getObjCSelType()); 2875243791Sdim for (ObjCMethodDecl::param_iterator PI = ArrayMethod->param_begin(), 2876243791Sdim E = ArrayMethod->param_end(); PI != E; ++PI) 2877243791Sdim ArgTypes.push_back((*PI)->getType()); 2878243791Sdim 2879243791Sdim QualType returnType = Exp->getType(); 2880243791Sdim // Get the type, we will need to reference it in a couple spots. 2881243791Sdim QualType msgSendType = MsgSendFlavor->getType(); 2882243791Sdim 2883243791Sdim // Create a reference to the objc_msgSend() declaration. 2884243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 2885243791Sdim VK_LValue, SourceLocation()); 2886243791Sdim 2887243791Sdim CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, 2888243791Sdim Context->getPointerType(Context->VoidTy), 2889243791Sdim CK_BitCast, DRE); 2890243791Sdim 2891243791Sdim // Now do the "normal" pointer to function cast. 2892243791Sdim QualType castType = 2893249423Sdim getSimpleFunctionType(returnType, ArgTypes, ArrayMethod->isVariadic()); 2894243791Sdim castType = Context->getPointerType(castType); 2895243791Sdim cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 2896243791Sdim cast); 2897243791Sdim 2898243791Sdim // Don't forget the parens to enforce the proper binding. 2899243791Sdim ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 2900243791Sdim 2901243791Sdim const FunctionType *FT = msgSendType->getAs<FunctionType>(); 2902243791Sdim CallExpr *CE = new (Context) CallExpr(*Context, PE, MsgExprs, 2903243791Sdim FT->getResultType(), VK_RValue, 2904243791Sdim EndLoc); 2905243791Sdim ReplaceStmt(Exp, CE); 2906243791Sdim return CE; 2907243791Sdim} 2908243791Sdim 2909243791SdimStmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) { 2910243791Sdim // synthesize declaration of helper functions needed in this routine. 2911243791Sdim if (!SelGetUidFunctionDecl) 2912243791Sdim SynthSelGetUidFunctionDecl(); 2913243791Sdim // use objc_msgSend() for all. 2914243791Sdim if (!MsgSendFunctionDecl) 2915243791Sdim SynthMsgSendFunctionDecl(); 2916243791Sdim if (!GetClassFunctionDecl) 2917243791Sdim SynthGetClassFunctionDecl(); 2918243791Sdim 2919243791Sdim FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 2920243791Sdim SourceLocation StartLoc = Exp->getLocStart(); 2921243791Sdim SourceLocation EndLoc = Exp->getLocEnd(); 2922243791Sdim 2923243791Sdim // Build the expression: __NSContainer_literal(int, ...).arr 2924243791Sdim QualType IntQT = Context->IntTy; 2925243791Sdim QualType NSDictFType = 2926249423Sdim getSimpleFunctionType(Context->VoidTy, IntQT, true); 2927243791Sdim std::string NSDictFName("__NSContainer_literal"); 2928243791Sdim FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName); 2929243791Sdim DeclRefExpr *NSDictDRE = 2930243791Sdim new (Context) DeclRefExpr(NSDictFD, false, NSDictFType, VK_RValue, 2931243791Sdim SourceLocation()); 2932243791Sdim 2933243791Sdim SmallVector<Expr*, 16> KeyExprs; 2934243791Sdim SmallVector<Expr*, 16> ValueExprs; 2935243791Sdim 2936243791Sdim unsigned NumElements = Exp->getNumElements(); 2937243791Sdim unsigned UnsignedIntSize = 2938243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 2939243791Sdim Expr *count = IntegerLiteral::Create(*Context, 2940243791Sdim llvm::APInt(UnsignedIntSize, NumElements), 2941243791Sdim Context->UnsignedIntTy, SourceLocation()); 2942243791Sdim KeyExprs.push_back(count); 2943243791Sdim ValueExprs.push_back(count); 2944243791Sdim for (unsigned i = 0; i < NumElements; i++) { 2945243791Sdim ObjCDictionaryElement Element = Exp->getKeyValueElement(i); 2946243791Sdim KeyExprs.push_back(Element.Key); 2947243791Sdim ValueExprs.push_back(Element.Value); 2948243791Sdim } 2949243791Sdim 2950243791Sdim // (const id [])objects 2951243791Sdim Expr *NSValueCallExpr = 2952243791Sdim new (Context) CallExpr(*Context, NSDictDRE, ValueExprs, 2953243791Sdim NSDictFType, VK_LValue, SourceLocation()); 2954243791Sdim 2955243791Sdim FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(), 2956243791Sdim SourceLocation(), 2957243791Sdim &Context->Idents.get("arr"), 2958243791Sdim Context->getPointerType(Context->VoidPtrTy), 0, 2959243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 2960243791Sdim ICIS_NoInit); 2961243791Sdim MemberExpr *DictLiteralValueME = 2962243791Sdim new (Context) MemberExpr(NSValueCallExpr, false, ARRFD, 2963243791Sdim SourceLocation(), 2964243791Sdim ARRFD->getType(), VK_LValue, 2965243791Sdim OK_Ordinary); 2966243791Sdim QualType ConstIdT = Context->getObjCIdType().withConst(); 2967243791Sdim CStyleCastExpr * DictValueObjects = 2968243791Sdim NoTypeInfoCStyleCastExpr(Context, 2969243791Sdim Context->getPointerType(ConstIdT), 2970243791Sdim CK_BitCast, 2971243791Sdim DictLiteralValueME); 2972243791Sdim // (const id <NSCopying> [])keys 2973243791Sdim Expr *NSKeyCallExpr = 2974243791Sdim new (Context) CallExpr(*Context, NSDictDRE, KeyExprs, 2975243791Sdim NSDictFType, VK_LValue, SourceLocation()); 2976243791Sdim 2977243791Sdim MemberExpr *DictLiteralKeyME = 2978243791Sdim new (Context) MemberExpr(NSKeyCallExpr, false, ARRFD, 2979243791Sdim SourceLocation(), 2980243791Sdim ARRFD->getType(), VK_LValue, 2981243791Sdim OK_Ordinary); 2982243791Sdim 2983243791Sdim CStyleCastExpr * DictKeyObjects = 2984243791Sdim NoTypeInfoCStyleCastExpr(Context, 2985243791Sdim Context->getPointerType(ConstIdT), 2986243791Sdim CK_BitCast, 2987243791Sdim DictLiteralKeyME); 2988243791Sdim 2989243791Sdim 2990243791Sdim 2991243791Sdim // Synthesize a call to objc_msgSend(). 2992243791Sdim SmallVector<Expr*, 32> MsgExprs; 2993243791Sdim SmallVector<Expr*, 4> ClsExprs; 2994243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2995243791Sdim QualType expType = Exp->getType(); 2996243791Sdim 2997243791Sdim // Create a call to objc_getClass("NSArray"). It will be th 1st argument. 2998243791Sdim ObjCInterfaceDecl *Class = 2999243791Sdim expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface(); 3000243791Sdim 3001243791Sdim IdentifierInfo *clsName = Class->getIdentifier(); 3002243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 3003243791Sdim clsName->getName(), 3004243791Sdim StringLiteral::Ascii, false, 3005243791Sdim argType, SourceLocation())); 3006243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 3007243791Sdim &ClsExprs[0], 3008243791Sdim ClsExprs.size(), 3009243791Sdim StartLoc, EndLoc); 3010243791Sdim MsgExprs.push_back(Cls); 3011243791Sdim 3012243791Sdim // Create a call to sel_registerName("arrayWithObjects:count:"). 3013243791Sdim // it will be the 2nd argument. 3014243791Sdim SmallVector<Expr*, 4> SelExprs; 3015243791Sdim ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod(); 3016243791Sdim SelExprs.push_back(StringLiteral::Create(*Context, 3017243791Sdim DictMethod->getSelector().getAsString(), 3018243791Sdim StringLiteral::Ascii, false, 3019243791Sdim argType, SourceLocation())); 3020243791Sdim CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 3021243791Sdim &SelExprs[0], SelExprs.size(), 3022243791Sdim StartLoc, EndLoc); 3023243791Sdim MsgExprs.push_back(SelExp); 3024243791Sdim 3025243791Sdim // (const id [])objects 3026243791Sdim MsgExprs.push_back(DictValueObjects); 3027243791Sdim 3028243791Sdim // (const id <NSCopying> [])keys 3029243791Sdim MsgExprs.push_back(DictKeyObjects); 3030243791Sdim 3031243791Sdim // (NSUInteger)cnt 3032243791Sdim Expr *cnt = IntegerLiteral::Create(*Context, 3033243791Sdim llvm::APInt(UnsignedIntSize, NumElements), 3034243791Sdim Context->UnsignedIntTy, SourceLocation()); 3035243791Sdim MsgExprs.push_back(cnt); 3036243791Sdim 3037243791Sdim 3038243791Sdim SmallVector<QualType, 8> ArgTypes; 3039243791Sdim ArgTypes.push_back(Context->getObjCIdType()); 3040243791Sdim ArgTypes.push_back(Context->getObjCSelType()); 3041243791Sdim for (ObjCMethodDecl::param_iterator PI = DictMethod->param_begin(), 3042243791Sdim E = DictMethod->param_end(); PI != E; ++PI) { 3043243791Sdim QualType T = (*PI)->getType(); 3044243791Sdim if (const PointerType* PT = T->getAs<PointerType>()) { 3045243791Sdim QualType PointeeTy = PT->getPointeeType(); 3046243791Sdim convertToUnqualifiedObjCType(PointeeTy); 3047243791Sdim T = Context->getPointerType(PointeeTy); 3048243791Sdim } 3049243791Sdim ArgTypes.push_back(T); 3050243791Sdim } 3051243791Sdim 3052243791Sdim QualType returnType = Exp->getType(); 3053243791Sdim // Get the type, we will need to reference it in a couple spots. 3054243791Sdim QualType msgSendType = MsgSendFlavor->getType(); 3055243791Sdim 3056243791Sdim // Create a reference to the objc_msgSend() declaration. 3057243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 3058243791Sdim VK_LValue, SourceLocation()); 3059243791Sdim 3060243791Sdim CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, 3061243791Sdim Context->getPointerType(Context->VoidTy), 3062243791Sdim CK_BitCast, DRE); 3063243791Sdim 3064243791Sdim // Now do the "normal" pointer to function cast. 3065243791Sdim QualType castType = 3066249423Sdim getSimpleFunctionType(returnType, ArgTypes, DictMethod->isVariadic()); 3067243791Sdim castType = Context->getPointerType(castType); 3068243791Sdim cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 3069243791Sdim cast); 3070243791Sdim 3071243791Sdim // Don't forget the parens to enforce the proper binding. 3072243791Sdim ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 3073243791Sdim 3074243791Sdim const FunctionType *FT = msgSendType->getAs<FunctionType>(); 3075243791Sdim CallExpr *CE = new (Context) CallExpr(*Context, PE, MsgExprs, 3076243791Sdim FT->getResultType(), VK_RValue, 3077243791Sdim EndLoc); 3078243791Sdim ReplaceStmt(Exp, CE); 3079243791Sdim return CE; 3080243791Sdim} 3081243791Sdim 3082243791Sdim// struct __rw_objc_super { 3083243791Sdim// struct objc_object *object; struct objc_object *superClass; 3084243791Sdim// }; 3085243791SdimQualType RewriteModernObjC::getSuperStructType() { 3086243791Sdim if (!SuperStructDecl) { 3087243791Sdim SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 3088243791Sdim SourceLocation(), SourceLocation(), 3089243791Sdim &Context->Idents.get("__rw_objc_super")); 3090243791Sdim QualType FieldTypes[2]; 3091243791Sdim 3092243791Sdim // struct objc_object *object; 3093243791Sdim FieldTypes[0] = Context->getObjCIdType(); 3094243791Sdim // struct objc_object *superClass; 3095243791Sdim FieldTypes[1] = Context->getObjCIdType(); 3096243791Sdim 3097243791Sdim // Create fields 3098243791Sdim for (unsigned i = 0; i < 2; ++i) { 3099243791Sdim SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, 3100243791Sdim SourceLocation(), 3101243791Sdim SourceLocation(), 0, 3102243791Sdim FieldTypes[i], 0, 3103243791Sdim /*BitWidth=*/0, 3104243791Sdim /*Mutable=*/false, 3105243791Sdim ICIS_NoInit)); 3106243791Sdim } 3107243791Sdim 3108243791Sdim SuperStructDecl->completeDefinition(); 3109243791Sdim } 3110243791Sdim return Context->getTagDeclType(SuperStructDecl); 3111243791Sdim} 3112243791Sdim 3113243791SdimQualType RewriteModernObjC::getConstantStringStructType() { 3114243791Sdim if (!ConstantStringDecl) { 3115243791Sdim ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 3116243791Sdim SourceLocation(), SourceLocation(), 3117243791Sdim &Context->Idents.get("__NSConstantStringImpl")); 3118243791Sdim QualType FieldTypes[4]; 3119243791Sdim 3120243791Sdim // struct objc_object *receiver; 3121243791Sdim FieldTypes[0] = Context->getObjCIdType(); 3122243791Sdim // int flags; 3123243791Sdim FieldTypes[1] = Context->IntTy; 3124243791Sdim // char *str; 3125243791Sdim FieldTypes[2] = Context->getPointerType(Context->CharTy); 3126243791Sdim // long length; 3127243791Sdim FieldTypes[3] = Context->LongTy; 3128243791Sdim 3129243791Sdim // Create fields 3130243791Sdim for (unsigned i = 0; i < 4; ++i) { 3131243791Sdim ConstantStringDecl->addDecl(FieldDecl::Create(*Context, 3132243791Sdim ConstantStringDecl, 3133243791Sdim SourceLocation(), 3134243791Sdim SourceLocation(), 0, 3135243791Sdim FieldTypes[i], 0, 3136243791Sdim /*BitWidth=*/0, 3137243791Sdim /*Mutable=*/true, 3138243791Sdim ICIS_NoInit)); 3139243791Sdim } 3140243791Sdim 3141243791Sdim ConstantStringDecl->completeDefinition(); 3142243791Sdim } 3143243791Sdim return Context->getTagDeclType(ConstantStringDecl); 3144243791Sdim} 3145243791Sdim 3146243791Sdim/// getFunctionSourceLocation - returns start location of a function 3147243791Sdim/// definition. Complication arises when function has declared as 3148243791Sdim/// extern "C" or extern "C" {...} 3149243791Sdimstatic SourceLocation getFunctionSourceLocation (RewriteModernObjC &R, 3150243791Sdim FunctionDecl *FD) { 3151243791Sdim if (FD->isExternC() && !FD->isMain()) { 3152243791Sdim const DeclContext *DC = FD->getDeclContext(); 3153243791Sdim if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC)) 3154243791Sdim // if it is extern "C" {...}, return function decl's own location. 3155243791Sdim if (!LSD->getRBraceLoc().isValid()) 3156243791Sdim return LSD->getExternLoc(); 3157243791Sdim } 3158249423Sdim if (FD->getStorageClass() != SC_None) 3159243791Sdim R.RewriteBlockLiteralFunctionDecl(FD); 3160243791Sdim return FD->getTypeSpecStartLoc(); 3161243791Sdim} 3162243791Sdim 3163243791Sdimvoid RewriteModernObjC::RewriteLineDirective(const Decl *D) { 3164243791Sdim 3165243791Sdim SourceLocation Location = D->getLocation(); 3166243791Sdim 3167249423Sdim if (Location.isFileID() && GenerateLineInfo) { 3168243791Sdim std::string LineString("\n#line "); 3169243791Sdim PresumedLoc PLoc = SM->getPresumedLoc(Location); 3170243791Sdim LineString += utostr(PLoc.getLine()); 3171243791Sdim LineString += " \""; 3172243791Sdim LineString += Lexer::Stringify(PLoc.getFilename()); 3173243791Sdim if (isa<ObjCMethodDecl>(D)) 3174243791Sdim LineString += "\""; 3175243791Sdim else LineString += "\"\n"; 3176243791Sdim 3177243791Sdim Location = D->getLocStart(); 3178243791Sdim if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 3179243791Sdim if (FD->isExternC() && !FD->isMain()) { 3180243791Sdim const DeclContext *DC = FD->getDeclContext(); 3181243791Sdim if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC)) 3182243791Sdim // if it is extern "C" {...}, return function decl's own location. 3183243791Sdim if (!LSD->getRBraceLoc().isValid()) 3184243791Sdim Location = LSD->getExternLoc(); 3185243791Sdim } 3186243791Sdim } 3187243791Sdim InsertText(Location, LineString); 3188243791Sdim } 3189243791Sdim} 3190243791Sdim 3191243791Sdim/// SynthMsgSendStretCallExpr - This routine translates message expression 3192243791Sdim/// into a call to objc_msgSend_stret() entry point. Tricky part is that 3193243791Sdim/// nil check on receiver must be performed before calling objc_msgSend_stret. 3194243791Sdim/// MsgSendStretFlavor - function declaration objc_msgSend_stret(...) 3195243791Sdim/// msgSendType - function type of objc_msgSend_stret(...) 3196243791Sdim/// returnType - Result type of the method being synthesized. 3197243791Sdim/// ArgTypes - type of the arguments passed to objc_msgSend_stret, starting with receiver type. 3198243791Sdim/// MsgExprs - list of argument expressions being passed to objc_msgSend_stret, 3199243791Sdim/// starting with receiver. 3200243791Sdim/// Method - Method being rewritten. 3201243791SdimExpr *RewriteModernObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, 3202243791Sdim QualType returnType, 3203243791Sdim SmallVectorImpl<QualType> &ArgTypes, 3204243791Sdim SmallVectorImpl<Expr*> &MsgExprs, 3205243791Sdim ObjCMethodDecl *Method) { 3206243791Sdim // Now do the "normal" pointer to function cast. 3207249423Sdim QualType castType = getSimpleFunctionType(returnType, ArgTypes, 3208249423Sdim Method ? Method->isVariadic() 3209249423Sdim : false); 3210243791Sdim castType = Context->getPointerType(castType); 3211243791Sdim 3212243791Sdim // build type for containing the objc_msgSend_stret object. 3213243791Sdim static unsigned stretCount=0; 3214243791Sdim std::string name = "__Stret"; name += utostr(stretCount); 3215243791Sdim std::string str = 3216243791Sdim "extern \"C\" void * __cdecl memset(void *_Dst, int _Val, size_t _Size);\n"; 3217263508Sdim str += "namespace {\n"; 3218243791Sdim str += "struct "; str += name; 3219243791Sdim str += " {\n\t"; 3220243791Sdim str += name; 3221243791Sdim str += "(id receiver, SEL sel"; 3222243791Sdim for (unsigned i = 2; i < ArgTypes.size(); i++) { 3223243791Sdim std::string ArgName = "arg"; ArgName += utostr(i); 3224243791Sdim ArgTypes[i].getAsStringInternal(ArgName, Context->getPrintingPolicy()); 3225243791Sdim str += ", "; str += ArgName; 3226243791Sdim } 3227243791Sdim // could be vararg. 3228243791Sdim for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) { 3229243791Sdim std::string ArgName = "arg"; ArgName += utostr(i); 3230243791Sdim MsgExprs[i]->getType().getAsStringInternal(ArgName, 3231243791Sdim Context->getPrintingPolicy()); 3232243791Sdim str += ", "; str += ArgName; 3233243791Sdim } 3234243791Sdim 3235243791Sdim str += ") {\n"; 3236263508Sdim str += "\t unsigned size = sizeof("; 3237263508Sdim str += returnType.getAsString(Context->getPrintingPolicy()); str += ");\n"; 3238263508Sdim 3239263508Sdim str += "\t if (size == 1 || size == 2 || size == 4 || size == 8)\n"; 3240263508Sdim 3241263508Sdim str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy()); 3242263508Sdim str += ")(void *)objc_msgSend)(receiver, sel"; 3243263508Sdim for (unsigned i = 2; i < ArgTypes.size(); i++) { 3244263508Sdim str += ", arg"; str += utostr(i); 3245263508Sdim } 3246263508Sdim // could be vararg. 3247263508Sdim for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) { 3248263508Sdim str += ", arg"; str += utostr(i); 3249263508Sdim } 3250263508Sdim str+= ");\n"; 3251263508Sdim 3252263508Sdim str += "\t else if (receiver == 0)\n"; 3253243791Sdim str += "\t memset((void*)&s, 0, sizeof(s));\n"; 3254243791Sdim str += "\t else\n"; 3255263508Sdim 3256263508Sdim 3257243791Sdim str += "\t s = (("; str += castType.getAsString(Context->getPrintingPolicy()); 3258243791Sdim str += ")(void *)objc_msgSend_stret)(receiver, sel"; 3259243791Sdim for (unsigned i = 2; i < ArgTypes.size(); i++) { 3260243791Sdim str += ", arg"; str += utostr(i); 3261243791Sdim } 3262243791Sdim // could be vararg. 3263243791Sdim for (unsigned i = ArgTypes.size(); i < MsgExprs.size(); i++) { 3264243791Sdim str += ", arg"; str += utostr(i); 3265243791Sdim } 3266263508Sdim str += ");\n"; 3267243791Sdim 3268263508Sdim 3269243791Sdim str += "\t}\n"; 3270243791Sdim str += "\t"; str += returnType.getAsString(Context->getPrintingPolicy()); 3271243791Sdim str += " s;\n"; 3272263508Sdim str += "};\n};\n\n"; 3273243791Sdim SourceLocation FunLocStart; 3274243791Sdim if (CurFunctionDef) 3275243791Sdim FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef); 3276243791Sdim else { 3277243791Sdim assert(CurMethodDef && "SynthMsgSendStretCallExpr - CurMethodDef is null"); 3278243791Sdim FunLocStart = CurMethodDef->getLocStart(); 3279243791Sdim } 3280243791Sdim 3281243791Sdim InsertText(FunLocStart, str); 3282243791Sdim ++stretCount; 3283243791Sdim 3284243791Sdim // AST for __Stretn(receiver, args).s; 3285243791Sdim IdentifierInfo *ID = &Context->Idents.get(name); 3286243791Sdim FunctionDecl *FD = FunctionDecl::Create(*Context, TUDecl, SourceLocation(), 3287249423Sdim SourceLocation(), ID, castType, 0, 3288249423Sdim SC_Extern, false, false); 3289243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, castType, VK_RValue, 3290243791Sdim SourceLocation()); 3291243791Sdim CallExpr *STCE = new (Context) CallExpr(*Context, DRE, MsgExprs, 3292243791Sdim castType, VK_LValue, SourceLocation()); 3293243791Sdim 3294243791Sdim FieldDecl *FieldD = FieldDecl::Create(*Context, 0, SourceLocation(), 3295243791Sdim SourceLocation(), 3296243791Sdim &Context->Idents.get("s"), 3297243791Sdim returnType, 0, 3298243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 3299243791Sdim ICIS_NoInit); 3300243791Sdim MemberExpr *ME = new (Context) MemberExpr(STCE, false, FieldD, SourceLocation(), 3301243791Sdim FieldD->getType(), VK_LValue, 3302243791Sdim OK_Ordinary); 3303243791Sdim 3304243791Sdim return ME; 3305243791Sdim} 3306243791Sdim 3307243791SdimStmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 3308243791Sdim SourceLocation StartLoc, 3309243791Sdim SourceLocation EndLoc) { 3310243791Sdim if (!SelGetUidFunctionDecl) 3311243791Sdim SynthSelGetUidFunctionDecl(); 3312243791Sdim if (!MsgSendFunctionDecl) 3313243791Sdim SynthMsgSendFunctionDecl(); 3314243791Sdim if (!MsgSendSuperFunctionDecl) 3315243791Sdim SynthMsgSendSuperFunctionDecl(); 3316243791Sdim if (!MsgSendStretFunctionDecl) 3317243791Sdim SynthMsgSendStretFunctionDecl(); 3318243791Sdim if (!MsgSendSuperStretFunctionDecl) 3319243791Sdim SynthMsgSendSuperStretFunctionDecl(); 3320243791Sdim if (!MsgSendFpretFunctionDecl) 3321243791Sdim SynthMsgSendFpretFunctionDecl(); 3322243791Sdim if (!GetClassFunctionDecl) 3323243791Sdim SynthGetClassFunctionDecl(); 3324243791Sdim if (!GetSuperClassFunctionDecl) 3325243791Sdim SynthGetSuperClassFunctionDecl(); 3326243791Sdim if (!GetMetaClassFunctionDecl) 3327243791Sdim SynthGetMetaClassFunctionDecl(); 3328243791Sdim 3329243791Sdim // default to objc_msgSend(). 3330243791Sdim FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 3331243791Sdim // May need to use objc_msgSend_stret() as well. 3332243791Sdim FunctionDecl *MsgSendStretFlavor = 0; 3333243791Sdim if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { 3334243791Sdim QualType resultType = mDecl->getResultType(); 3335243791Sdim if (resultType->isRecordType()) 3336243791Sdim MsgSendStretFlavor = MsgSendStretFunctionDecl; 3337243791Sdim else if (resultType->isRealFloatingType()) 3338243791Sdim MsgSendFlavor = MsgSendFpretFunctionDecl; 3339243791Sdim } 3340243791Sdim 3341243791Sdim // Synthesize a call to objc_msgSend(). 3342243791Sdim SmallVector<Expr*, 8> MsgExprs; 3343243791Sdim switch (Exp->getReceiverKind()) { 3344243791Sdim case ObjCMessageExpr::SuperClass: { 3345243791Sdim MsgSendFlavor = MsgSendSuperFunctionDecl; 3346243791Sdim if (MsgSendStretFlavor) 3347243791Sdim MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 3348243791Sdim assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 3349243791Sdim 3350243791Sdim ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 3351243791Sdim 3352243791Sdim SmallVector<Expr*, 4> InitExprs; 3353243791Sdim 3354243791Sdim // set the receiver to self, the first argument to all methods. 3355243791Sdim InitExprs.push_back( 3356243791Sdim NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 3357243791Sdim CK_BitCast, 3358243791Sdim new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 3359243791Sdim false, 3360243791Sdim Context->getObjCIdType(), 3361243791Sdim VK_RValue, 3362243791Sdim SourceLocation())) 3363243791Sdim ); // set the 'receiver'. 3364243791Sdim 3365243791Sdim // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 3366243791Sdim SmallVector<Expr*, 8> ClsExprs; 3367243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 3368243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 3369243791Sdim ClassDecl->getIdentifier()->getName(), 3370243791Sdim StringLiteral::Ascii, false, 3371243791Sdim argType, SourceLocation())); 3372243791Sdim // (Class)objc_getClass("CurrentClass") 3373243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, 3374243791Sdim &ClsExprs[0], 3375243791Sdim ClsExprs.size(), 3376243791Sdim StartLoc, 3377243791Sdim EndLoc); 3378243791Sdim ClsExprs.clear(); 3379243791Sdim ClsExprs.push_back(Cls); 3380243791Sdim Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 3381243791Sdim &ClsExprs[0], ClsExprs.size(), 3382243791Sdim StartLoc, EndLoc); 3383243791Sdim 3384243791Sdim // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 3385243791Sdim // To turn off a warning, type-cast to 'id' 3386243791Sdim InitExprs.push_back( // set 'super class', using class_getSuperclass(). 3387243791Sdim NoTypeInfoCStyleCastExpr(Context, 3388243791Sdim Context->getObjCIdType(), 3389243791Sdim CK_BitCast, Cls)); 3390243791Sdim // struct __rw_objc_super 3391243791Sdim QualType superType = getSuperStructType(); 3392243791Sdim Expr *SuperRep; 3393243791Sdim 3394243791Sdim if (LangOpts.MicrosoftExt) { 3395263508Sdim SynthSuperConstructorFunctionDecl(); 3396263508Sdim // Simulate a constructor call... 3397263508Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl, 3398243791Sdim false, superType, VK_LValue, 3399243791Sdim SourceLocation()); 3400243791Sdim SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs, 3401243791Sdim superType, VK_LValue, 3402243791Sdim SourceLocation()); 3403243791Sdim // The code for super is a little tricky to prevent collision with 3404243791Sdim // the structure definition in the header. The rewriter has it's own 3405243791Sdim // internal definition (__rw_objc_super) that is uses. This is why 3406243791Sdim // we need the cast below. For example: 3407243791Sdim // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 3408243791Sdim // 3409243791Sdim SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 3410243791Sdim Context->getPointerType(SuperRep->getType()), 3411243791Sdim VK_RValue, OK_Ordinary, 3412243791Sdim SourceLocation()); 3413243791Sdim SuperRep = NoTypeInfoCStyleCastExpr(Context, 3414243791Sdim Context->getPointerType(superType), 3415243791Sdim CK_BitCast, SuperRep); 3416243791Sdim } else { 3417243791Sdim // (struct __rw_objc_super) { <exprs from above> } 3418243791Sdim InitListExpr *ILE = 3419243791Sdim new (Context) InitListExpr(*Context, SourceLocation(), InitExprs, 3420243791Sdim SourceLocation()); 3421243791Sdim TypeSourceInfo *superTInfo 3422243791Sdim = Context->getTrivialTypeSourceInfo(superType); 3423243791Sdim SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 3424243791Sdim superType, VK_LValue, 3425243791Sdim ILE, false); 3426243791Sdim // struct __rw_objc_super * 3427243791Sdim SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 3428243791Sdim Context->getPointerType(SuperRep->getType()), 3429243791Sdim VK_RValue, OK_Ordinary, 3430243791Sdim SourceLocation()); 3431243791Sdim } 3432243791Sdim MsgExprs.push_back(SuperRep); 3433243791Sdim break; 3434243791Sdim } 3435243791Sdim 3436243791Sdim case ObjCMessageExpr::Class: { 3437243791Sdim SmallVector<Expr*, 8> ClsExprs; 3438243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 3439243791Sdim ObjCInterfaceDecl *Class 3440243791Sdim = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface(); 3441243791Sdim IdentifierInfo *clsName = Class->getIdentifier(); 3442243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 3443243791Sdim clsName->getName(), 3444243791Sdim StringLiteral::Ascii, false, 3445243791Sdim argType, SourceLocation())); 3446243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 3447243791Sdim &ClsExprs[0], 3448243791Sdim ClsExprs.size(), 3449243791Sdim StartLoc, EndLoc); 3450243791Sdim CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 3451243791Sdim Context->getObjCIdType(), 3452243791Sdim CK_BitCast, Cls); 3453243791Sdim MsgExprs.push_back(ArgExpr); 3454243791Sdim break; 3455243791Sdim } 3456243791Sdim 3457243791Sdim case ObjCMessageExpr::SuperInstance:{ 3458243791Sdim MsgSendFlavor = MsgSendSuperFunctionDecl; 3459243791Sdim if (MsgSendStretFlavor) 3460243791Sdim MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 3461243791Sdim assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 3462243791Sdim ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 3463243791Sdim SmallVector<Expr*, 4> InitExprs; 3464243791Sdim 3465243791Sdim InitExprs.push_back( 3466243791Sdim NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 3467243791Sdim CK_BitCast, 3468243791Sdim new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 3469243791Sdim false, 3470243791Sdim Context->getObjCIdType(), 3471243791Sdim VK_RValue, SourceLocation())) 3472243791Sdim ); // set the 'receiver'. 3473243791Sdim 3474243791Sdim // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 3475243791Sdim SmallVector<Expr*, 8> ClsExprs; 3476243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 3477243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 3478243791Sdim ClassDecl->getIdentifier()->getName(), 3479243791Sdim StringLiteral::Ascii, false, argType, 3480243791Sdim SourceLocation())); 3481243791Sdim // (Class)objc_getClass("CurrentClass") 3482243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 3483243791Sdim &ClsExprs[0], 3484243791Sdim ClsExprs.size(), 3485243791Sdim StartLoc, EndLoc); 3486243791Sdim ClsExprs.clear(); 3487243791Sdim ClsExprs.push_back(Cls); 3488243791Sdim Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 3489243791Sdim &ClsExprs[0], ClsExprs.size(), 3490243791Sdim StartLoc, EndLoc); 3491243791Sdim 3492243791Sdim // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 3493243791Sdim // To turn off a warning, type-cast to 'id' 3494243791Sdim InitExprs.push_back( 3495243791Sdim // set 'super class', using class_getSuperclass(). 3496243791Sdim NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 3497243791Sdim CK_BitCast, Cls)); 3498243791Sdim // struct __rw_objc_super 3499243791Sdim QualType superType = getSuperStructType(); 3500243791Sdim Expr *SuperRep; 3501243791Sdim 3502243791Sdim if (LangOpts.MicrosoftExt) { 3503263508Sdim SynthSuperConstructorFunctionDecl(); 3504263508Sdim // Simulate a constructor call... 3505263508Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl, 3506243791Sdim false, superType, VK_LValue, 3507243791Sdim SourceLocation()); 3508243791Sdim SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs, 3509243791Sdim superType, VK_LValue, SourceLocation()); 3510243791Sdim // The code for super is a little tricky to prevent collision with 3511243791Sdim // the structure definition in the header. The rewriter has it's own 3512243791Sdim // internal definition (__rw_objc_super) that is uses. This is why 3513243791Sdim // we need the cast below. For example: 3514243791Sdim // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 3515243791Sdim // 3516243791Sdim SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 3517243791Sdim Context->getPointerType(SuperRep->getType()), 3518243791Sdim VK_RValue, OK_Ordinary, 3519243791Sdim SourceLocation()); 3520243791Sdim SuperRep = NoTypeInfoCStyleCastExpr(Context, 3521243791Sdim Context->getPointerType(superType), 3522243791Sdim CK_BitCast, SuperRep); 3523243791Sdim } else { 3524243791Sdim // (struct __rw_objc_super) { <exprs from above> } 3525243791Sdim InitListExpr *ILE = 3526243791Sdim new (Context) InitListExpr(*Context, SourceLocation(), InitExprs, 3527243791Sdim SourceLocation()); 3528243791Sdim TypeSourceInfo *superTInfo 3529243791Sdim = Context->getTrivialTypeSourceInfo(superType); 3530243791Sdim SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 3531243791Sdim superType, VK_RValue, ILE, 3532243791Sdim false); 3533243791Sdim } 3534243791Sdim MsgExprs.push_back(SuperRep); 3535243791Sdim break; 3536243791Sdim } 3537243791Sdim 3538243791Sdim case ObjCMessageExpr::Instance: { 3539243791Sdim // Remove all type-casts because it may contain objc-style types; e.g. 3540243791Sdim // Foo<Proto> *. 3541243791Sdim Expr *recExpr = Exp->getInstanceReceiver(); 3542243791Sdim while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) 3543243791Sdim recExpr = CE->getSubExpr(); 3544243791Sdim CastKind CK = recExpr->getType()->isObjCObjectPointerType() 3545243791Sdim ? CK_BitCast : recExpr->getType()->isBlockPointerType() 3546243791Sdim ? CK_BlockPointerToObjCPointerCast 3547243791Sdim : CK_CPointerToObjCPointerCast; 3548243791Sdim 3549243791Sdim recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 3550243791Sdim CK, recExpr); 3551243791Sdim MsgExprs.push_back(recExpr); 3552243791Sdim break; 3553243791Sdim } 3554243791Sdim } 3555243791Sdim 3556243791Sdim // Create a call to sel_registerName("selName"), it will be the 2nd argument. 3557243791Sdim SmallVector<Expr*, 8> SelExprs; 3558243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 3559243791Sdim SelExprs.push_back(StringLiteral::Create(*Context, 3560243791Sdim Exp->getSelector().getAsString(), 3561243791Sdim StringLiteral::Ascii, false, 3562243791Sdim argType, SourceLocation())); 3563243791Sdim CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 3564243791Sdim &SelExprs[0], SelExprs.size(), 3565243791Sdim StartLoc, 3566243791Sdim EndLoc); 3567243791Sdim MsgExprs.push_back(SelExp); 3568243791Sdim 3569243791Sdim // Now push any user supplied arguments. 3570243791Sdim for (unsigned i = 0; i < Exp->getNumArgs(); i++) { 3571243791Sdim Expr *userExpr = Exp->getArg(i); 3572243791Sdim // Make all implicit casts explicit...ICE comes in handy:-) 3573243791Sdim if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { 3574243791Sdim // Reuse the ICE type, it is exactly what the doctor ordered. 3575243791Sdim QualType type = ICE->getType(); 3576243791Sdim if (needToScanForQualifiers(type)) 3577243791Sdim type = Context->getObjCIdType(); 3578243791Sdim // Make sure we convert "type (^)(...)" to "type (*)(...)". 3579243791Sdim (void)convertBlockPointerToFunctionPointer(type); 3580243791Sdim const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 3581243791Sdim CastKind CK; 3582243791Sdim if (SubExpr->getType()->isIntegralType(*Context) && 3583243791Sdim type->isBooleanType()) { 3584243791Sdim CK = CK_IntegralToBoolean; 3585243791Sdim } else if (type->isObjCObjectPointerType()) { 3586243791Sdim if (SubExpr->getType()->isBlockPointerType()) { 3587243791Sdim CK = CK_BlockPointerToObjCPointerCast; 3588243791Sdim } else if (SubExpr->getType()->isPointerType()) { 3589243791Sdim CK = CK_CPointerToObjCPointerCast; 3590243791Sdim } else { 3591243791Sdim CK = CK_BitCast; 3592243791Sdim } 3593243791Sdim } else { 3594243791Sdim CK = CK_BitCast; 3595243791Sdim } 3596243791Sdim 3597243791Sdim userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); 3598243791Sdim } 3599243791Sdim // Make id<P...> cast into an 'id' cast. 3600243791Sdim else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { 3601243791Sdim if (CE->getType()->isObjCQualifiedIdType()) { 3602243791Sdim while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) 3603243791Sdim userExpr = CE->getSubExpr(); 3604243791Sdim CastKind CK; 3605243791Sdim if (userExpr->getType()->isIntegralType(*Context)) { 3606243791Sdim CK = CK_IntegralToPointer; 3607243791Sdim } else if (userExpr->getType()->isBlockPointerType()) { 3608243791Sdim CK = CK_BlockPointerToObjCPointerCast; 3609243791Sdim } else if (userExpr->getType()->isPointerType()) { 3610243791Sdim CK = CK_CPointerToObjCPointerCast; 3611243791Sdim } else { 3612243791Sdim CK = CK_BitCast; 3613243791Sdim } 3614243791Sdim userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 3615243791Sdim CK, userExpr); 3616243791Sdim } 3617243791Sdim } 3618243791Sdim MsgExprs.push_back(userExpr); 3619243791Sdim // We've transferred the ownership to MsgExprs. For now, we *don't* null 3620243791Sdim // out the argument in the original expression (since we aren't deleting 3621243791Sdim // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info. 3622243791Sdim //Exp->setArg(i, 0); 3623243791Sdim } 3624243791Sdim // Generate the funky cast. 3625243791Sdim CastExpr *cast; 3626243791Sdim SmallVector<QualType, 8> ArgTypes; 3627243791Sdim QualType returnType; 3628243791Sdim 3629243791Sdim // Push 'id' and 'SEL', the 2 implicit arguments. 3630243791Sdim if (MsgSendFlavor == MsgSendSuperFunctionDecl) 3631243791Sdim ArgTypes.push_back(Context->getPointerType(getSuperStructType())); 3632243791Sdim else 3633243791Sdim ArgTypes.push_back(Context->getObjCIdType()); 3634243791Sdim ArgTypes.push_back(Context->getObjCSelType()); 3635243791Sdim if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { 3636243791Sdim // Push any user argument types. 3637243791Sdim for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 3638243791Sdim E = OMD->param_end(); PI != E; ++PI) { 3639243791Sdim QualType t = (*PI)->getType()->isObjCQualifiedIdType() 3640243791Sdim ? Context->getObjCIdType() 3641243791Sdim : (*PI)->getType(); 3642243791Sdim // Make sure we convert "t (^)(...)" to "t (*)(...)". 3643243791Sdim (void)convertBlockPointerToFunctionPointer(t); 3644243791Sdim ArgTypes.push_back(t); 3645243791Sdim } 3646243791Sdim returnType = Exp->getType(); 3647243791Sdim convertToUnqualifiedObjCType(returnType); 3648243791Sdim (void)convertBlockPointerToFunctionPointer(returnType); 3649243791Sdim } else { 3650243791Sdim returnType = Context->getObjCIdType(); 3651243791Sdim } 3652243791Sdim // Get the type, we will need to reference it in a couple spots. 3653243791Sdim QualType msgSendType = MsgSendFlavor->getType(); 3654243791Sdim 3655243791Sdim // Create a reference to the objc_msgSend() declaration. 3656243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 3657243791Sdim VK_LValue, SourceLocation()); 3658243791Sdim 3659243791Sdim // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 3660243791Sdim // If we don't do this cast, we get the following bizarre warning/note: 3661243791Sdim // xx.m:13: warning: function called through a non-compatible type 3662243791Sdim // xx.m:13: note: if this code is reached, the program will abort 3663243791Sdim cast = NoTypeInfoCStyleCastExpr(Context, 3664243791Sdim Context->getPointerType(Context->VoidTy), 3665243791Sdim CK_BitCast, DRE); 3666243791Sdim 3667243791Sdim // Now do the "normal" pointer to function cast. 3668249423Sdim // If we don't have a method decl, force a variadic cast. 3669249423Sdim const ObjCMethodDecl *MD = Exp->getMethodDecl(); 3670243791Sdim QualType castType = 3671249423Sdim getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true); 3672243791Sdim castType = Context->getPointerType(castType); 3673243791Sdim cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 3674243791Sdim cast); 3675243791Sdim 3676243791Sdim // Don't forget the parens to enforce the proper binding. 3677243791Sdim ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 3678243791Sdim 3679243791Sdim const FunctionType *FT = msgSendType->getAs<FunctionType>(); 3680243791Sdim CallExpr *CE = new (Context) CallExpr(*Context, PE, MsgExprs, 3681243791Sdim FT->getResultType(), VK_RValue, EndLoc); 3682243791Sdim Stmt *ReplacingStmt = CE; 3683243791Sdim if (MsgSendStretFlavor) { 3684243791Sdim // We have the method which returns a struct/union. Must also generate 3685243791Sdim // call to objc_msgSend_stret and hang both varieties on a conditional 3686243791Sdim // expression which dictate which one to envoke depending on size of 3687243791Sdim // method's return type. 3688243791Sdim 3689263508Sdim Expr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor, 3690263508Sdim returnType, 3691243791Sdim ArgTypes, MsgExprs, 3692243791Sdim Exp->getMethodDecl()); 3693263508Sdim ReplacingStmt = STCE; 3694243791Sdim } 3695243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 3696243791Sdim return ReplacingStmt; 3697243791Sdim} 3698243791Sdim 3699243791SdimStmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { 3700243791Sdim Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(), 3701243791Sdim Exp->getLocEnd()); 3702243791Sdim 3703243791Sdim // Now do the actual rewrite. 3704243791Sdim ReplaceStmt(Exp, ReplacingStmt); 3705243791Sdim 3706243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 3707243791Sdim return ReplacingStmt; 3708243791Sdim} 3709243791Sdim 3710243791Sdim// typedef struct objc_object Protocol; 3711243791SdimQualType RewriteModernObjC::getProtocolType() { 3712243791Sdim if (!ProtocolTypeDecl) { 3713243791Sdim TypeSourceInfo *TInfo 3714243791Sdim = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); 3715243791Sdim ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, 3716243791Sdim SourceLocation(), SourceLocation(), 3717243791Sdim &Context->Idents.get("Protocol"), 3718243791Sdim TInfo); 3719243791Sdim } 3720243791Sdim return Context->getTypeDeclType(ProtocolTypeDecl); 3721243791Sdim} 3722243791Sdim 3723243791Sdim/// RewriteObjCProtocolExpr - Rewrite a protocol expression into 3724243791Sdim/// a synthesized/forward data reference (to the protocol's metadata). 3725243791Sdim/// The forward references (and metadata) are generated in 3726243791Sdim/// RewriteModernObjC::HandleTranslationUnit(). 3727243791SdimStmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { 3728243791Sdim std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" + 3729243791Sdim Exp->getProtocol()->getNameAsString(); 3730243791Sdim IdentifierInfo *ID = &Context->Idents.get(Name); 3731243791Sdim VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 3732243791Sdim SourceLocation(), ID, getProtocolType(), 0, 3733249423Sdim SC_Extern); 3734243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(), 3735243791Sdim VK_LValue, SourceLocation()); 3736243791Sdim Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, 3737243791Sdim Context->getPointerType(DRE->getType()), 3738243791Sdim VK_RValue, OK_Ordinary, SourceLocation()); 3739243791Sdim CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), 3740243791Sdim CK_BitCast, 3741243791Sdim DerefExpr); 3742243791Sdim ReplaceStmt(Exp, castExpr); 3743243791Sdim ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl()); 3744243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 3745243791Sdim return castExpr; 3746243791Sdim 3747243791Sdim} 3748243791Sdim 3749243791Sdimbool RewriteModernObjC::BufferContainsPPDirectives(const char *startBuf, 3750243791Sdim const char *endBuf) { 3751243791Sdim while (startBuf < endBuf) { 3752243791Sdim if (*startBuf == '#') { 3753243791Sdim // Skip whitespace. 3754243791Sdim for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf) 3755243791Sdim ; 3756243791Sdim if (!strncmp(startBuf, "if", strlen("if")) || 3757243791Sdim !strncmp(startBuf, "ifdef", strlen("ifdef")) || 3758243791Sdim !strncmp(startBuf, "ifndef", strlen("ifndef")) || 3759243791Sdim !strncmp(startBuf, "define", strlen("define")) || 3760243791Sdim !strncmp(startBuf, "undef", strlen("undef")) || 3761243791Sdim !strncmp(startBuf, "else", strlen("else")) || 3762243791Sdim !strncmp(startBuf, "elif", strlen("elif")) || 3763243791Sdim !strncmp(startBuf, "endif", strlen("endif")) || 3764243791Sdim !strncmp(startBuf, "pragma", strlen("pragma")) || 3765243791Sdim !strncmp(startBuf, "include", strlen("include")) || 3766243791Sdim !strncmp(startBuf, "import", strlen("import")) || 3767243791Sdim !strncmp(startBuf, "include_next", strlen("include_next"))) 3768243791Sdim return true; 3769243791Sdim } 3770243791Sdim startBuf++; 3771243791Sdim } 3772243791Sdim return false; 3773243791Sdim} 3774243791Sdim 3775243791Sdim/// IsTagDefinedInsideClass - This routine checks that a named tagged type 3776243791Sdim/// is defined inside an objective-c class. If so, it returns true. 3777243791Sdimbool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, 3778243791Sdim TagDecl *Tag, 3779243791Sdim bool &IsNamedDefinition) { 3780243791Sdim if (!IDecl) 3781243791Sdim return false; 3782243791Sdim SourceLocation TagLocation; 3783243791Sdim if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) { 3784243791Sdim RD = RD->getDefinition(); 3785243791Sdim if (!RD || !RD->getDeclName().getAsIdentifierInfo()) 3786243791Sdim return false; 3787243791Sdim IsNamedDefinition = true; 3788243791Sdim TagLocation = RD->getLocation(); 3789243791Sdim return Context->getSourceManager().isBeforeInTranslationUnit( 3790243791Sdim IDecl->getLocation(), TagLocation); 3791243791Sdim } 3792243791Sdim if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) { 3793243791Sdim if (!ED || !ED->getDeclName().getAsIdentifierInfo()) 3794243791Sdim return false; 3795243791Sdim IsNamedDefinition = true; 3796243791Sdim TagLocation = ED->getLocation(); 3797243791Sdim return Context->getSourceManager().isBeforeInTranslationUnit( 3798243791Sdim IDecl->getLocation(), TagLocation); 3799243791Sdim 3800243791Sdim } 3801243791Sdim return false; 3802243791Sdim} 3803243791Sdim 3804243791Sdim/// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer. 3805243791Sdim/// It handles elaborated types, as well as enum types in the process. 3806243791Sdimbool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type, 3807243791Sdim std::string &Result) { 3808243791Sdim if (isa<TypedefType>(Type)) { 3809243791Sdim Result += "\t"; 3810243791Sdim return false; 3811243791Sdim } 3812243791Sdim 3813243791Sdim if (Type->isArrayType()) { 3814243791Sdim QualType ElemTy = Context->getBaseElementType(Type); 3815243791Sdim return RewriteObjCFieldDeclType(ElemTy, Result); 3816243791Sdim } 3817243791Sdim else if (Type->isRecordType()) { 3818243791Sdim RecordDecl *RD = Type->getAs<RecordType>()->getDecl(); 3819243791Sdim if (RD->isCompleteDefinition()) { 3820243791Sdim if (RD->isStruct()) 3821243791Sdim Result += "\n\tstruct "; 3822243791Sdim else if (RD->isUnion()) 3823243791Sdim Result += "\n\tunion "; 3824243791Sdim else 3825243791Sdim assert(false && "class not allowed as an ivar type"); 3826243791Sdim 3827243791Sdim Result += RD->getName(); 3828243791Sdim if (GlobalDefinedTags.count(RD)) { 3829243791Sdim // struct/union is defined globally, use it. 3830243791Sdim Result += " "; 3831243791Sdim return true; 3832243791Sdim } 3833243791Sdim Result += " {\n"; 3834243791Sdim for (RecordDecl::field_iterator i = RD->field_begin(), 3835243791Sdim e = RD->field_end(); i != e; ++i) { 3836243791Sdim FieldDecl *FD = *i; 3837243791Sdim RewriteObjCFieldDecl(FD, Result); 3838243791Sdim } 3839243791Sdim Result += "\t} "; 3840243791Sdim return true; 3841243791Sdim } 3842243791Sdim } 3843243791Sdim else if (Type->isEnumeralType()) { 3844243791Sdim EnumDecl *ED = Type->getAs<EnumType>()->getDecl(); 3845243791Sdim if (ED->isCompleteDefinition()) { 3846243791Sdim Result += "\n\tenum "; 3847243791Sdim Result += ED->getName(); 3848243791Sdim if (GlobalDefinedTags.count(ED)) { 3849243791Sdim // Enum is globall defined, use it. 3850243791Sdim Result += " "; 3851243791Sdim return true; 3852243791Sdim } 3853243791Sdim 3854243791Sdim Result += " {\n"; 3855243791Sdim for (EnumDecl::enumerator_iterator EC = ED->enumerator_begin(), 3856243791Sdim ECEnd = ED->enumerator_end(); EC != ECEnd; ++EC) { 3857243791Sdim Result += "\t"; Result += EC->getName(); Result += " = "; 3858243791Sdim llvm::APSInt Val = EC->getInitVal(); 3859243791Sdim Result += Val.toString(10); 3860243791Sdim Result += ",\n"; 3861243791Sdim } 3862243791Sdim Result += "\t} "; 3863243791Sdim return true; 3864243791Sdim } 3865243791Sdim } 3866243791Sdim 3867243791Sdim Result += "\t"; 3868243791Sdim convertObjCTypeToCStyleType(Type); 3869243791Sdim return false; 3870243791Sdim} 3871243791Sdim 3872243791Sdim 3873243791Sdim/// RewriteObjCFieldDecl - This routine rewrites a field into the buffer. 3874243791Sdim/// It handles elaborated types, as well as enum types in the process. 3875243791Sdimvoid RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, 3876243791Sdim std::string &Result) { 3877243791Sdim QualType Type = fieldDecl->getType(); 3878243791Sdim std::string Name = fieldDecl->getNameAsString(); 3879243791Sdim 3880243791Sdim bool EleboratedType = RewriteObjCFieldDeclType(Type, Result); 3881243791Sdim if (!EleboratedType) 3882243791Sdim Type.getAsStringInternal(Name, Context->getPrintingPolicy()); 3883243791Sdim Result += Name; 3884243791Sdim if (fieldDecl->isBitField()) { 3885243791Sdim Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context)); 3886243791Sdim } 3887243791Sdim else if (EleboratedType && Type->isArrayType()) { 3888249423Sdim const ArrayType *AT = Context->getAsArrayType(Type); 3889249423Sdim do { 3890249423Sdim if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { 3891243791Sdim Result += "["; 3892243791Sdim llvm::APInt Dim = CAT->getSize(); 3893243791Sdim Result += utostr(Dim.getZExtValue()); 3894243791Sdim Result += "]"; 3895243791Sdim } 3896249423Sdim AT = Context->getAsArrayType(AT->getElementType()); 3897249423Sdim } while (AT); 3898243791Sdim } 3899243791Sdim 3900243791Sdim Result += ";\n"; 3901243791Sdim} 3902243791Sdim 3903243791Sdim/// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined 3904243791Sdim/// named aggregate types into the input buffer. 3905243791Sdimvoid RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl, 3906243791Sdim std::string &Result) { 3907243791Sdim QualType Type = fieldDecl->getType(); 3908243791Sdim if (isa<TypedefType>(Type)) 3909243791Sdim return; 3910243791Sdim if (Type->isArrayType()) 3911243791Sdim Type = Context->getBaseElementType(Type); 3912243791Sdim ObjCContainerDecl *IDecl = 3913243791Sdim dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext()); 3914243791Sdim 3915243791Sdim TagDecl *TD = 0; 3916243791Sdim if (Type->isRecordType()) { 3917243791Sdim TD = Type->getAs<RecordType>()->getDecl(); 3918243791Sdim } 3919243791Sdim else if (Type->isEnumeralType()) { 3920243791Sdim TD = Type->getAs<EnumType>()->getDecl(); 3921243791Sdim } 3922243791Sdim 3923243791Sdim if (TD) { 3924243791Sdim if (GlobalDefinedTags.count(TD)) 3925243791Sdim return; 3926243791Sdim 3927243791Sdim bool IsNamedDefinition = false; 3928243791Sdim if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) { 3929243791Sdim RewriteObjCFieldDeclType(Type, Result); 3930243791Sdim Result += ";"; 3931243791Sdim } 3932243791Sdim if (IsNamedDefinition) 3933243791Sdim GlobalDefinedTags.insert(TD); 3934243791Sdim } 3935243791Sdim 3936243791Sdim} 3937243791Sdim 3938249423Sdimunsigned RewriteModernObjC::ObjCIvarBitfieldGroupNo(ObjCIvarDecl *IV) { 3939249423Sdim const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); 3940249423Sdim if (ObjCInterefaceHasBitfieldGroups.count(CDecl)) { 3941249423Sdim return IvarGroupNumber[IV]; 3942249423Sdim } 3943249423Sdim unsigned GroupNo = 0; 3944249423Sdim SmallVector<const ObjCIvarDecl *, 8> IVars; 3945249423Sdim for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 3946249423Sdim IVD; IVD = IVD->getNextIvar()) 3947249423Sdim IVars.push_back(IVD); 3948249423Sdim 3949249423Sdim for (unsigned i = 0, e = IVars.size(); i < e; i++) 3950249423Sdim if (IVars[i]->isBitField()) { 3951249423Sdim IvarGroupNumber[IVars[i++]] = ++GroupNo; 3952249423Sdim while (i < e && IVars[i]->isBitField()) 3953249423Sdim IvarGroupNumber[IVars[i++]] = GroupNo; 3954249423Sdim if (i < e) 3955249423Sdim --i; 3956249423Sdim } 3957249423Sdim 3958249423Sdim ObjCInterefaceHasBitfieldGroups.insert(CDecl); 3959249423Sdim return IvarGroupNumber[IV]; 3960249423Sdim} 3961249423Sdim 3962249423SdimQualType RewriteModernObjC::SynthesizeBitfieldGroupStructType( 3963249423Sdim ObjCIvarDecl *IV, 3964249423Sdim SmallVectorImpl<ObjCIvarDecl *> &IVars) { 3965249423Sdim std::string StructTagName; 3966249423Sdim ObjCIvarBitfieldGroupType(IV, StructTagName); 3967249423Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, 3968249423Sdim Context->getTranslationUnitDecl(), 3969249423Sdim SourceLocation(), SourceLocation(), 3970249423Sdim &Context->Idents.get(StructTagName)); 3971249423Sdim for (unsigned i=0, e = IVars.size(); i < e; i++) { 3972249423Sdim ObjCIvarDecl *Ivar = IVars[i]; 3973249423Sdim RD->addDecl(FieldDecl::Create(*Context, RD, SourceLocation(), SourceLocation(), 3974249423Sdim &Context->Idents.get(Ivar->getName()), 3975249423Sdim Ivar->getType(), 3976249423Sdim 0, /*Expr *BW */Ivar->getBitWidth(), false, 3977249423Sdim ICIS_NoInit)); 3978249423Sdim } 3979249423Sdim RD->completeDefinition(); 3980249423Sdim return Context->getTagDeclType(RD); 3981249423Sdim} 3982249423Sdim 3983249423SdimQualType RewriteModernObjC::GetGroupRecordTypeForObjCIvarBitfield(ObjCIvarDecl *IV) { 3984249423Sdim const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); 3985249423Sdim unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); 3986249423Sdim std::pair<const ObjCInterfaceDecl*, unsigned> tuple = std::make_pair(CDecl, GroupNo); 3987249423Sdim if (GroupRecordType.count(tuple)) 3988249423Sdim return GroupRecordType[tuple]; 3989249423Sdim 3990249423Sdim SmallVector<ObjCIvarDecl *, 8> IVars; 3991249423Sdim for (const ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 3992249423Sdim IVD; IVD = IVD->getNextIvar()) { 3993249423Sdim if (IVD->isBitField()) 3994249423Sdim IVars.push_back(const_cast<ObjCIvarDecl *>(IVD)); 3995249423Sdim else { 3996249423Sdim if (!IVars.empty()) { 3997249423Sdim unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]); 3998249423Sdim // Generate the struct type for this group of bitfield ivars. 3999249423Sdim GroupRecordType[std::make_pair(CDecl, GroupNo)] = 4000249423Sdim SynthesizeBitfieldGroupStructType(IVars[0], IVars); 4001249423Sdim IVars.clear(); 4002249423Sdim } 4003249423Sdim } 4004249423Sdim } 4005249423Sdim if (!IVars.empty()) { 4006249423Sdim // Do the last one. 4007249423Sdim unsigned GroupNo = ObjCIvarBitfieldGroupNo(IVars[0]); 4008249423Sdim GroupRecordType[std::make_pair(CDecl, GroupNo)] = 4009249423Sdim SynthesizeBitfieldGroupStructType(IVars[0], IVars); 4010249423Sdim } 4011249423Sdim QualType RetQT = GroupRecordType[tuple]; 4012249423Sdim assert(!RetQT.isNull() && "GetGroupRecordTypeForObjCIvarBitfield struct type is NULL"); 4013249423Sdim 4014249423Sdim return RetQT; 4015249423Sdim} 4016249423Sdim 4017249423Sdim/// ObjCIvarBitfieldGroupDecl - Names field decl. for ivar bitfield group. 4018249423Sdim/// Name would be: classname__GRBF_n where n is the group number for this ivar. 4019249423Sdimvoid RewriteModernObjC::ObjCIvarBitfieldGroupDecl(ObjCIvarDecl *IV, 4020249423Sdim std::string &Result) { 4021249423Sdim const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); 4022249423Sdim Result += CDecl->getName(); 4023249423Sdim Result += "__GRBF_"; 4024249423Sdim unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); 4025249423Sdim Result += utostr(GroupNo); 4026249423Sdim return; 4027249423Sdim} 4028249423Sdim 4029249423Sdim/// ObjCIvarBitfieldGroupType - Names struct type for ivar bitfield group. 4030249423Sdim/// Name of the struct would be: classname__T_n where n is the group number for 4031249423Sdim/// this ivar. 4032249423Sdimvoid RewriteModernObjC::ObjCIvarBitfieldGroupType(ObjCIvarDecl *IV, 4033249423Sdim std::string &Result) { 4034249423Sdim const ObjCInterfaceDecl *CDecl = IV->getContainingInterface(); 4035249423Sdim Result += CDecl->getName(); 4036249423Sdim Result += "__T_"; 4037249423Sdim unsigned GroupNo = ObjCIvarBitfieldGroupNo(IV); 4038249423Sdim Result += utostr(GroupNo); 4039249423Sdim return; 4040249423Sdim} 4041249423Sdim 4042249423Sdim/// ObjCIvarBitfieldGroupOffset - Names symbol for ivar bitfield group field offset. 4043249423Sdim/// Name would be: OBJC_IVAR_$_classname__GRBF_n where n is the group number for 4044249423Sdim/// this ivar. 4045249423Sdimvoid RewriteModernObjC::ObjCIvarBitfieldGroupOffset(ObjCIvarDecl *IV, 4046249423Sdim std::string &Result) { 4047249423Sdim Result += "OBJC_IVAR_$_"; 4048249423Sdim ObjCIvarBitfieldGroupDecl(IV, Result); 4049249423Sdim} 4050249423Sdim 4051249423Sdim#define SKIP_BITFIELDS(IX, ENDIX, VEC) { \ 4052249423Sdim while ((IX < ENDIX) && VEC[IX]->isBitField()) \ 4053249423Sdim ++IX; \ 4054249423Sdim if (IX < ENDIX) \ 4055249423Sdim --IX; \ 4056249423Sdim} 4057249423Sdim 4058243791Sdim/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to 4059243791Sdim/// an objective-c class with ivars. 4060243791Sdimvoid RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 4061243791Sdim std::string &Result) { 4062243791Sdim assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); 4063243791Sdim assert(CDecl->getName() != "" && 4064243791Sdim "Name missing in SynthesizeObjCInternalStruct"); 4065243791Sdim ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); 4066243791Sdim SmallVector<ObjCIvarDecl *, 8> IVars; 4067243791Sdim for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 4068243791Sdim IVD; IVD = IVD->getNextIvar()) 4069243791Sdim IVars.push_back(IVD); 4070243791Sdim 4071243791Sdim SourceLocation LocStart = CDecl->getLocStart(); 4072243791Sdim SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc(); 4073243791Sdim 4074243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 4075243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 4076243791Sdim 4077243791Sdim // If no ivars and no root or if its root, directly or indirectly, 4078243791Sdim // have no ivars (thus not synthesized) then no need to synthesize this class. 4079243791Sdim if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) && 4080243791Sdim (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { 4081243791Sdim endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 4082243791Sdim ReplaceText(LocStart, endBuf-startBuf, Result); 4083243791Sdim return; 4084243791Sdim } 4085243791Sdim 4086243791Sdim // Insert named struct/union definitions inside class to 4087243791Sdim // outer scope. This follows semantics of locally defined 4088243791Sdim // struct/unions in objective-c classes. 4089243791Sdim for (unsigned i = 0, e = IVars.size(); i < e; i++) 4090243791Sdim RewriteLocallyDefinedNamedAggregates(IVars[i], Result); 4091249423Sdim 4092249423Sdim // Insert named structs which are syntheized to group ivar bitfields 4093249423Sdim // to outer scope as well. 4094249423Sdim for (unsigned i = 0, e = IVars.size(); i < e; i++) 4095249423Sdim if (IVars[i]->isBitField()) { 4096249423Sdim ObjCIvarDecl *IV = IVars[i]; 4097249423Sdim QualType QT = GetGroupRecordTypeForObjCIvarBitfield(IV); 4098249423Sdim RewriteObjCFieldDeclType(QT, Result); 4099249423Sdim Result += ";"; 4100249423Sdim // skip over ivar bitfields in this group. 4101249423Sdim SKIP_BITFIELDS(i , e, IVars); 4102249423Sdim } 4103249423Sdim 4104243791Sdim Result += "\nstruct "; 4105243791Sdim Result += CDecl->getNameAsString(); 4106243791Sdim Result += "_IMPL {\n"; 4107243791Sdim 4108243791Sdim if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 4109243791Sdim Result += "\tstruct "; Result += RCDecl->getNameAsString(); 4110243791Sdim Result += "_IMPL "; Result += RCDecl->getNameAsString(); 4111243791Sdim Result += "_IVARS;\n"; 4112243791Sdim } 4113243791Sdim 4114249423Sdim for (unsigned i = 0, e = IVars.size(); i < e; i++) { 4115249423Sdim if (IVars[i]->isBitField()) { 4116249423Sdim ObjCIvarDecl *IV = IVars[i]; 4117249423Sdim Result += "\tstruct "; 4118249423Sdim ObjCIvarBitfieldGroupType(IV, Result); Result += " "; 4119249423Sdim ObjCIvarBitfieldGroupDecl(IV, Result); Result += ";\n"; 4120249423Sdim // skip over ivar bitfields in this group. 4121249423Sdim SKIP_BITFIELDS(i , e, IVars); 4122249423Sdim } 4123249423Sdim else 4124249423Sdim RewriteObjCFieldDecl(IVars[i], Result); 4125249423Sdim } 4126243791Sdim 4127243791Sdim Result += "};\n"; 4128243791Sdim endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 4129243791Sdim ReplaceText(LocStart, endBuf-startBuf, Result); 4130243791Sdim // Mark this struct as having been generated. 4131243791Sdim if (!ObjCSynthesizedStructs.insert(CDecl)) 4132243791Sdim llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct"); 4133243791Sdim} 4134243791Sdim 4135243791Sdim/// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which 4136243791Sdim/// have been referenced in an ivar access expression. 4137243791Sdimvoid RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, 4138243791Sdim std::string &Result) { 4139243791Sdim // write out ivar offset symbols which have been referenced in an ivar 4140243791Sdim // access expression. 4141243791Sdim llvm::SmallPtrSet<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl]; 4142243791Sdim if (Ivars.empty()) 4143243791Sdim return; 4144249423Sdim 4145249423Sdim llvm::DenseSet<std::pair<const ObjCInterfaceDecl*, unsigned> > GroupSymbolOutput; 4146243791Sdim for (llvm::SmallPtrSet<ObjCIvarDecl *, 8>::iterator i = Ivars.begin(), 4147243791Sdim e = Ivars.end(); i != e; i++) { 4148243791Sdim ObjCIvarDecl *IvarDecl = (*i); 4149249423Sdim const ObjCInterfaceDecl *IDecl = IvarDecl->getContainingInterface(); 4150249423Sdim unsigned GroupNo = 0; 4151249423Sdim if (IvarDecl->isBitField()) { 4152249423Sdim GroupNo = ObjCIvarBitfieldGroupNo(IvarDecl); 4153249423Sdim if (GroupSymbolOutput.count(std::make_pair(IDecl, GroupNo))) 4154249423Sdim continue; 4155249423Sdim } 4156243791Sdim Result += "\n"; 4157243791Sdim if (LangOpts.MicrosoftExt) 4158243791Sdim Result += "__declspec(allocate(\".objc_ivar$B\")) "; 4159243791Sdim Result += "extern \"C\" "; 4160243791Sdim if (LangOpts.MicrosoftExt && 4161243791Sdim IvarDecl->getAccessControl() != ObjCIvarDecl::Private && 4162243791Sdim IvarDecl->getAccessControl() != ObjCIvarDecl::Package) 4163243791Sdim Result += "__declspec(dllimport) "; 4164243791Sdim 4165243791Sdim Result += "unsigned long "; 4166249423Sdim if (IvarDecl->isBitField()) { 4167249423Sdim ObjCIvarBitfieldGroupOffset(IvarDecl, Result); 4168249423Sdim GroupSymbolOutput.insert(std::make_pair(IDecl, GroupNo)); 4169249423Sdim } 4170249423Sdim else 4171249423Sdim WriteInternalIvarName(CDecl, IvarDecl, Result); 4172243791Sdim Result += ";"; 4173243791Sdim } 4174243791Sdim} 4175243791Sdim 4176243791Sdim//===----------------------------------------------------------------------===// 4177243791Sdim// Meta Data Emission 4178243791Sdim//===----------------------------------------------------------------------===// 4179243791Sdim 4180243791Sdim 4181243791Sdim/// RewriteImplementations - This routine rewrites all method implementations 4182243791Sdim/// and emits meta-data. 4183243791Sdim 4184243791Sdimvoid RewriteModernObjC::RewriteImplementations() { 4185243791Sdim int ClsDefCount = ClassImplementation.size(); 4186243791Sdim int CatDefCount = CategoryImplementation.size(); 4187243791Sdim 4188243791Sdim // Rewrite implemented methods 4189243791Sdim for (int i = 0; i < ClsDefCount; i++) { 4190243791Sdim ObjCImplementationDecl *OIMP = ClassImplementation[i]; 4191243791Sdim ObjCInterfaceDecl *CDecl = OIMP->getClassInterface(); 4192243791Sdim if (CDecl->isImplicitInterfaceDecl()) 4193243791Sdim assert(false && 4194243791Sdim "Legacy implicit interface rewriting not supported in moder abi"); 4195243791Sdim RewriteImplementationDecl(OIMP); 4196243791Sdim } 4197243791Sdim 4198243791Sdim for (int i = 0; i < CatDefCount; i++) { 4199243791Sdim ObjCCategoryImplDecl *CIMP = CategoryImplementation[i]; 4200243791Sdim ObjCInterfaceDecl *CDecl = CIMP->getClassInterface(); 4201243791Sdim if (CDecl->isImplicitInterfaceDecl()) 4202243791Sdim assert(false && 4203243791Sdim "Legacy implicit interface rewriting not supported in moder abi"); 4204243791Sdim RewriteImplementationDecl(CIMP); 4205243791Sdim } 4206243791Sdim} 4207243791Sdim 4208243791Sdimvoid RewriteModernObjC::RewriteByRefString(std::string &ResultStr, 4209243791Sdim const std::string &Name, 4210243791Sdim ValueDecl *VD, bool def) { 4211243791Sdim assert(BlockByRefDeclNo.count(VD) && 4212243791Sdim "RewriteByRefString: ByRef decl missing"); 4213243791Sdim if (def) 4214243791Sdim ResultStr += "struct "; 4215243791Sdim ResultStr += "__Block_byref_" + Name + 4216243791Sdim "_" + utostr(BlockByRefDeclNo[VD]) ; 4217243791Sdim} 4218243791Sdim 4219243791Sdimstatic bool HasLocalVariableExternalStorage(ValueDecl *VD) { 4220243791Sdim if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 4221243791Sdim return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage()); 4222243791Sdim return false; 4223243791Sdim} 4224243791Sdim 4225243791Sdimstd::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, 4226243791Sdim StringRef funcName, 4227243791Sdim std::string Tag) { 4228243791Sdim const FunctionType *AFT = CE->getFunctionType(); 4229243791Sdim QualType RT = AFT->getResultType(); 4230243791Sdim std::string StructRef = "struct " + Tag; 4231243791Sdim SourceLocation BlockLoc = CE->getExprLoc(); 4232243791Sdim std::string S; 4233243791Sdim ConvertSourceLocationToLineDirective(BlockLoc, S); 4234243791Sdim 4235243791Sdim S += "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" + 4236243791Sdim funcName.str() + "_block_func_" + utostr(i); 4237243791Sdim 4238243791Sdim BlockDecl *BD = CE->getBlockDecl(); 4239243791Sdim 4240243791Sdim if (isa<FunctionNoProtoType>(AFT)) { 4241243791Sdim // No user-supplied arguments. Still need to pass in a pointer to the 4242243791Sdim // block (to reference imported block decl refs). 4243243791Sdim S += "(" + StructRef + " *__cself)"; 4244243791Sdim } else if (BD->param_empty()) { 4245243791Sdim S += "(" + StructRef + " *__cself)"; 4246243791Sdim } else { 4247243791Sdim const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); 4248243791Sdim assert(FT && "SynthesizeBlockFunc: No function proto"); 4249243791Sdim S += '('; 4250243791Sdim // first add the implicit argument. 4251243791Sdim S += StructRef + " *__cself, "; 4252243791Sdim std::string ParamStr; 4253243791Sdim for (BlockDecl::param_iterator AI = BD->param_begin(), 4254243791Sdim E = BD->param_end(); AI != E; ++AI) { 4255243791Sdim if (AI != BD->param_begin()) S += ", "; 4256243791Sdim ParamStr = (*AI)->getNameAsString(); 4257243791Sdim QualType QT = (*AI)->getType(); 4258243791Sdim (void)convertBlockPointerToFunctionPointer(QT); 4259243791Sdim QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); 4260243791Sdim S += ParamStr; 4261243791Sdim } 4262243791Sdim if (FT->isVariadic()) { 4263243791Sdim if (!BD->param_empty()) S += ", "; 4264243791Sdim S += "..."; 4265243791Sdim } 4266243791Sdim S += ')'; 4267243791Sdim } 4268243791Sdim S += " {\n"; 4269243791Sdim 4270243791Sdim // Create local declarations to avoid rewriting all closure decl ref exprs. 4271243791Sdim // First, emit a declaration for all "by ref" decls. 4272263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 4273243791Sdim E = BlockByRefDecls.end(); I != E; ++I) { 4274243791Sdim S += " "; 4275243791Sdim std::string Name = (*I)->getNameAsString(); 4276243791Sdim std::string TypeString; 4277243791Sdim RewriteByRefString(TypeString, Name, (*I)); 4278243791Sdim TypeString += " *"; 4279243791Sdim Name = TypeString + Name; 4280243791Sdim S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; 4281243791Sdim } 4282243791Sdim // Next, emit a declaration for all "by copy" declarations. 4283263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 4284243791Sdim E = BlockByCopyDecls.end(); I != E; ++I) { 4285243791Sdim S += " "; 4286243791Sdim // Handle nested closure invocation. For example: 4287243791Sdim // 4288243791Sdim // void (^myImportedClosure)(void); 4289243791Sdim // myImportedClosure = ^(void) { setGlobalInt(x + y); }; 4290243791Sdim // 4291243791Sdim // void (^anotherClosure)(void); 4292243791Sdim // anotherClosure = ^(void) { 4293243791Sdim // myImportedClosure(); // import and invoke the closure 4294243791Sdim // }; 4295243791Sdim // 4296243791Sdim if (isTopLevelBlockPointerType((*I)->getType())) { 4297243791Sdim RewriteBlockPointerTypeVariable(S, (*I)); 4298243791Sdim S += " = ("; 4299243791Sdim RewriteBlockPointerType(S, (*I)->getType()); 4300243791Sdim S += ")"; 4301243791Sdim S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n"; 4302243791Sdim } 4303243791Sdim else { 4304243791Sdim std::string Name = (*I)->getNameAsString(); 4305243791Sdim QualType QT = (*I)->getType(); 4306243791Sdim if (HasLocalVariableExternalStorage(*I)) 4307243791Sdim QT = Context->getPointerType(QT); 4308243791Sdim QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 4309243791Sdim S += Name + " = __cself->" + 4310243791Sdim (*I)->getNameAsString() + "; // bound by copy\n"; 4311243791Sdim } 4312243791Sdim } 4313243791Sdim std::string RewrittenStr = RewrittenBlockExprs[CE]; 4314243791Sdim const char *cstr = RewrittenStr.c_str(); 4315243791Sdim while (*cstr++ != '{') ; 4316243791Sdim S += cstr; 4317243791Sdim S += "\n"; 4318243791Sdim return S; 4319243791Sdim} 4320243791Sdim 4321243791Sdimstd::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 4322243791Sdim StringRef funcName, 4323243791Sdim std::string Tag) { 4324243791Sdim std::string StructRef = "struct " + Tag; 4325243791Sdim std::string S = "static void __"; 4326243791Sdim 4327243791Sdim S += funcName; 4328243791Sdim S += "_block_copy_" + utostr(i); 4329243791Sdim S += "(" + StructRef; 4330243791Sdim S += "*dst, " + StructRef; 4331243791Sdim S += "*src) {"; 4332243791Sdim for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 4333243791Sdim E = ImportedBlockDecls.end(); I != E; ++I) { 4334243791Sdim ValueDecl *VD = (*I); 4335243791Sdim S += "_Block_object_assign((void*)&dst->"; 4336243791Sdim S += (*I)->getNameAsString(); 4337243791Sdim S += ", (void*)src->"; 4338243791Sdim S += (*I)->getNameAsString(); 4339243791Sdim if (BlockByRefDeclsPtrSet.count((*I))) 4340243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 4341243791Sdim else if (VD->getType()->isBlockPointerType()) 4342243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 4343243791Sdim else 4344243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 4345243791Sdim } 4346243791Sdim S += "}\n"; 4347243791Sdim 4348243791Sdim S += "\nstatic void __"; 4349243791Sdim S += funcName; 4350243791Sdim S += "_block_dispose_" + utostr(i); 4351243791Sdim S += "(" + StructRef; 4352243791Sdim S += "*src) {"; 4353243791Sdim for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 4354243791Sdim E = ImportedBlockDecls.end(); I != E; ++I) { 4355243791Sdim ValueDecl *VD = (*I); 4356243791Sdim S += "_Block_object_dispose((void*)src->"; 4357243791Sdim S += (*I)->getNameAsString(); 4358243791Sdim if (BlockByRefDeclsPtrSet.count((*I))) 4359243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 4360243791Sdim else if (VD->getType()->isBlockPointerType()) 4361243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 4362243791Sdim else 4363243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 4364243791Sdim } 4365243791Sdim S += "}\n"; 4366243791Sdim return S; 4367243791Sdim} 4368243791Sdim 4369243791Sdimstd::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 4370243791Sdim std::string Desc) { 4371243791Sdim std::string S = "\nstruct " + Tag; 4372243791Sdim std::string Constructor = " " + Tag; 4373243791Sdim 4374243791Sdim S += " {\n struct __block_impl impl;\n"; 4375243791Sdim S += " struct " + Desc; 4376243791Sdim S += "* Desc;\n"; 4377243791Sdim 4378243791Sdim Constructor += "(void *fp, "; // Invoke function pointer. 4379243791Sdim Constructor += "struct " + Desc; // Descriptor pointer. 4380243791Sdim Constructor += " *desc"; 4381243791Sdim 4382243791Sdim if (BlockDeclRefs.size()) { 4383243791Sdim // Output all "by copy" declarations. 4384263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 4385243791Sdim E = BlockByCopyDecls.end(); I != E; ++I) { 4386243791Sdim S += " "; 4387243791Sdim std::string FieldName = (*I)->getNameAsString(); 4388243791Sdim std::string ArgName = "_" + FieldName; 4389243791Sdim // Handle nested closure invocation. For example: 4390243791Sdim // 4391243791Sdim // void (^myImportedBlock)(void); 4392243791Sdim // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 4393243791Sdim // 4394243791Sdim // void (^anotherBlock)(void); 4395243791Sdim // anotherBlock = ^(void) { 4396243791Sdim // myImportedBlock(); // import and invoke the closure 4397243791Sdim // }; 4398243791Sdim // 4399243791Sdim if (isTopLevelBlockPointerType((*I)->getType())) { 4400243791Sdim S += "struct __block_impl *"; 4401243791Sdim Constructor += ", void *" + ArgName; 4402243791Sdim } else { 4403243791Sdim QualType QT = (*I)->getType(); 4404243791Sdim if (HasLocalVariableExternalStorage(*I)) 4405243791Sdim QT = Context->getPointerType(QT); 4406243791Sdim QT.getAsStringInternal(FieldName, Context->getPrintingPolicy()); 4407243791Sdim QT.getAsStringInternal(ArgName, Context->getPrintingPolicy()); 4408243791Sdim Constructor += ", " + ArgName; 4409243791Sdim } 4410243791Sdim S += FieldName + ";\n"; 4411243791Sdim } 4412243791Sdim // Output all "by ref" declarations. 4413263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 4414243791Sdim E = BlockByRefDecls.end(); I != E; ++I) { 4415243791Sdim S += " "; 4416243791Sdim std::string FieldName = (*I)->getNameAsString(); 4417243791Sdim std::string ArgName = "_" + FieldName; 4418243791Sdim { 4419243791Sdim std::string TypeString; 4420243791Sdim RewriteByRefString(TypeString, FieldName, (*I)); 4421243791Sdim TypeString += " *"; 4422243791Sdim FieldName = TypeString + FieldName; 4423243791Sdim ArgName = TypeString + ArgName; 4424243791Sdim Constructor += ", " + ArgName; 4425243791Sdim } 4426243791Sdim S += FieldName + "; // by ref\n"; 4427243791Sdim } 4428243791Sdim // Finish writing the constructor. 4429243791Sdim Constructor += ", int flags=0)"; 4430243791Sdim // Initialize all "by copy" arguments. 4431243791Sdim bool firsTime = true; 4432263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 4433243791Sdim E = BlockByCopyDecls.end(); I != E; ++I) { 4434243791Sdim std::string Name = (*I)->getNameAsString(); 4435243791Sdim if (firsTime) { 4436243791Sdim Constructor += " : "; 4437243791Sdim firsTime = false; 4438243791Sdim } 4439243791Sdim else 4440243791Sdim Constructor += ", "; 4441243791Sdim if (isTopLevelBlockPointerType((*I)->getType())) 4442243791Sdim Constructor += Name + "((struct __block_impl *)_" + Name + ")"; 4443243791Sdim else 4444243791Sdim Constructor += Name + "(_" + Name + ")"; 4445243791Sdim } 4446243791Sdim // Initialize all "by ref" arguments. 4447263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 4448243791Sdim E = BlockByRefDecls.end(); I != E; ++I) { 4449243791Sdim std::string Name = (*I)->getNameAsString(); 4450243791Sdim if (firsTime) { 4451243791Sdim Constructor += " : "; 4452243791Sdim firsTime = false; 4453243791Sdim } 4454243791Sdim else 4455243791Sdim Constructor += ", "; 4456243791Sdim Constructor += Name + "(_" + Name + "->__forwarding)"; 4457243791Sdim } 4458243791Sdim 4459243791Sdim Constructor += " {\n"; 4460243791Sdim if (GlobalVarDecl) 4461243791Sdim Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 4462243791Sdim else 4463243791Sdim Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 4464243791Sdim Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 4465243791Sdim 4466243791Sdim Constructor += " Desc = desc;\n"; 4467243791Sdim } else { 4468243791Sdim // Finish writing the constructor. 4469243791Sdim Constructor += ", int flags=0) {\n"; 4470243791Sdim if (GlobalVarDecl) 4471243791Sdim Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 4472243791Sdim else 4473243791Sdim Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 4474243791Sdim Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 4475243791Sdim Constructor += " Desc = desc;\n"; 4476243791Sdim } 4477243791Sdim Constructor += " "; 4478243791Sdim Constructor += "}\n"; 4479243791Sdim S += Constructor; 4480243791Sdim S += "};\n"; 4481243791Sdim return S; 4482243791Sdim} 4483243791Sdim 4484243791Sdimstd::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag, 4485243791Sdim std::string ImplTag, int i, 4486243791Sdim StringRef FunName, 4487243791Sdim unsigned hasCopy) { 4488243791Sdim std::string S = "\nstatic struct " + DescTag; 4489243791Sdim 4490243791Sdim S += " {\n size_t reserved;\n"; 4491243791Sdim S += " size_t Block_size;\n"; 4492243791Sdim if (hasCopy) { 4493243791Sdim S += " void (*copy)(struct "; 4494243791Sdim S += ImplTag; S += "*, struct "; 4495243791Sdim S += ImplTag; S += "*);\n"; 4496243791Sdim 4497243791Sdim S += " void (*dispose)(struct "; 4498243791Sdim S += ImplTag; S += "*);\n"; 4499243791Sdim } 4500243791Sdim S += "} "; 4501243791Sdim 4502243791Sdim S += DescTag + "_DATA = { 0, sizeof(struct "; 4503243791Sdim S += ImplTag + ")"; 4504243791Sdim if (hasCopy) { 4505243791Sdim S += ", __" + FunName.str() + "_block_copy_" + utostr(i); 4506243791Sdim S += ", __" + FunName.str() + "_block_dispose_" + utostr(i); 4507243791Sdim } 4508243791Sdim S += "};\n"; 4509243791Sdim return S; 4510243791Sdim} 4511243791Sdim 4512243791Sdimvoid RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, 4513243791Sdim StringRef FunName) { 4514243791Sdim bool RewriteSC = (GlobalVarDecl && 4515243791Sdim !Blocks.empty() && 4516243791Sdim GlobalVarDecl->getStorageClass() == SC_Static && 4517243791Sdim GlobalVarDecl->getType().getCVRQualifiers()); 4518243791Sdim if (RewriteSC) { 4519243791Sdim std::string SC(" void __"); 4520243791Sdim SC += GlobalVarDecl->getNameAsString(); 4521243791Sdim SC += "() {}"; 4522243791Sdim InsertText(FunLocStart, SC); 4523243791Sdim } 4524243791Sdim 4525243791Sdim // Insert closures that were part of the function. 4526243791Sdim for (unsigned i = 0, count=0; i < Blocks.size(); i++) { 4527243791Sdim CollectBlockDeclRefInfo(Blocks[i]); 4528243791Sdim // Need to copy-in the inner copied-in variables not actually used in this 4529243791Sdim // block. 4530243791Sdim for (int j = 0; j < InnerDeclRefsCount[i]; j++) { 4531243791Sdim DeclRefExpr *Exp = InnerDeclRefs[count++]; 4532243791Sdim ValueDecl *VD = Exp->getDecl(); 4533243791Sdim BlockDeclRefs.push_back(Exp); 4534243791Sdim if (!VD->hasAttr<BlocksAttr>()) { 4535243791Sdim if (!BlockByCopyDeclsPtrSet.count(VD)) { 4536243791Sdim BlockByCopyDeclsPtrSet.insert(VD); 4537243791Sdim BlockByCopyDecls.push_back(VD); 4538243791Sdim } 4539243791Sdim continue; 4540243791Sdim } 4541243791Sdim 4542243791Sdim if (!BlockByRefDeclsPtrSet.count(VD)) { 4543243791Sdim BlockByRefDeclsPtrSet.insert(VD); 4544243791Sdim BlockByRefDecls.push_back(VD); 4545243791Sdim } 4546243791Sdim 4547243791Sdim // imported objects in the inner blocks not used in the outer 4548243791Sdim // blocks must be copied/disposed in the outer block as well. 4549243791Sdim if (VD->getType()->isObjCObjectPointerType() || 4550243791Sdim VD->getType()->isBlockPointerType()) 4551243791Sdim ImportedBlockDecls.insert(VD); 4552243791Sdim } 4553243791Sdim 4554243791Sdim std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i); 4555243791Sdim std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i); 4556243791Sdim 4557243791Sdim std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); 4558243791Sdim 4559243791Sdim InsertText(FunLocStart, CI); 4560243791Sdim 4561243791Sdim std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); 4562243791Sdim 4563243791Sdim InsertText(FunLocStart, CF); 4564243791Sdim 4565243791Sdim if (ImportedBlockDecls.size()) { 4566243791Sdim std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); 4567243791Sdim InsertText(FunLocStart, HF); 4568243791Sdim } 4569243791Sdim std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, 4570243791Sdim ImportedBlockDecls.size() > 0); 4571243791Sdim InsertText(FunLocStart, BD); 4572243791Sdim 4573243791Sdim BlockDeclRefs.clear(); 4574243791Sdim BlockByRefDecls.clear(); 4575243791Sdim BlockByRefDeclsPtrSet.clear(); 4576243791Sdim BlockByCopyDecls.clear(); 4577243791Sdim BlockByCopyDeclsPtrSet.clear(); 4578243791Sdim ImportedBlockDecls.clear(); 4579243791Sdim } 4580243791Sdim if (RewriteSC) { 4581243791Sdim // Must insert any 'const/volatile/static here. Since it has been 4582243791Sdim // removed as result of rewriting of block literals. 4583243791Sdim std::string SC; 4584243791Sdim if (GlobalVarDecl->getStorageClass() == SC_Static) 4585243791Sdim SC = "static "; 4586243791Sdim if (GlobalVarDecl->getType().isConstQualified()) 4587243791Sdim SC += "const "; 4588243791Sdim if (GlobalVarDecl->getType().isVolatileQualified()) 4589243791Sdim SC += "volatile "; 4590243791Sdim if (GlobalVarDecl->getType().isRestrictQualified()) 4591243791Sdim SC += "restrict "; 4592243791Sdim InsertText(FunLocStart, SC); 4593243791Sdim } 4594243791Sdim if (GlobalConstructionExp) { 4595243791Sdim // extra fancy dance for global literal expression. 4596243791Sdim 4597243791Sdim // Always the latest block expression on the block stack. 4598243791Sdim std::string Tag = "__"; 4599243791Sdim Tag += FunName; 4600243791Sdim Tag += "_block_impl_"; 4601243791Sdim Tag += utostr(Blocks.size()-1); 4602243791Sdim std::string globalBuf = "static "; 4603243791Sdim globalBuf += Tag; globalBuf += " "; 4604243791Sdim std::string SStr; 4605243791Sdim 4606243791Sdim llvm::raw_string_ostream constructorExprBuf(SStr); 4607243791Sdim GlobalConstructionExp->printPretty(constructorExprBuf, 0, 4608243791Sdim PrintingPolicy(LangOpts)); 4609243791Sdim globalBuf += constructorExprBuf.str(); 4610243791Sdim globalBuf += ";\n"; 4611243791Sdim InsertText(FunLocStart, globalBuf); 4612243791Sdim GlobalConstructionExp = 0; 4613243791Sdim } 4614243791Sdim 4615243791Sdim Blocks.clear(); 4616243791Sdim InnerDeclRefsCount.clear(); 4617243791Sdim InnerDeclRefs.clear(); 4618243791Sdim RewrittenBlockExprs.clear(); 4619243791Sdim} 4620243791Sdim 4621243791Sdimvoid RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { 4622243791Sdim SourceLocation FunLocStart = 4623243791Sdim (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD) 4624243791Sdim : FD->getTypeSpecStartLoc(); 4625243791Sdim StringRef FuncName = FD->getName(); 4626243791Sdim 4627243791Sdim SynthesizeBlockLiterals(FunLocStart, FuncName); 4628243791Sdim} 4629243791Sdim 4630243791Sdimstatic void BuildUniqueMethodName(std::string &Name, 4631243791Sdim ObjCMethodDecl *MD) { 4632243791Sdim ObjCInterfaceDecl *IFace = MD->getClassInterface(); 4633243791Sdim Name = IFace->getName(); 4634243791Sdim Name += "__" + MD->getSelector().getAsString(); 4635243791Sdim // Convert colons to underscores. 4636243791Sdim std::string::size_type loc = 0; 4637243791Sdim while ((loc = Name.find(":", loc)) != std::string::npos) 4638243791Sdim Name.replace(loc, 1, "_"); 4639243791Sdim} 4640243791Sdim 4641243791Sdimvoid RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { 4642243791Sdim //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); 4643243791Sdim //SourceLocation FunLocStart = MD->getLocStart(); 4644243791Sdim SourceLocation FunLocStart = MD->getLocStart(); 4645243791Sdim std::string FuncName; 4646243791Sdim BuildUniqueMethodName(FuncName, MD); 4647243791Sdim SynthesizeBlockLiterals(FunLocStart, FuncName); 4648243791Sdim} 4649243791Sdim 4650243791Sdimvoid RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) { 4651243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 4652243791Sdim if (*CI) { 4653243791Sdim if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) 4654243791Sdim GetBlockDeclRefExprs(CBE->getBody()); 4655243791Sdim else 4656243791Sdim GetBlockDeclRefExprs(*CI); 4657243791Sdim } 4658243791Sdim // Handle specific things. 4659243791Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 4660243791Sdim if (DRE->refersToEnclosingLocal()) { 4661243791Sdim // FIXME: Handle enums. 4662243791Sdim if (!isa<FunctionDecl>(DRE->getDecl())) 4663243791Sdim BlockDeclRefs.push_back(DRE); 4664243791Sdim if (HasLocalVariableExternalStorage(DRE->getDecl())) 4665243791Sdim BlockDeclRefs.push_back(DRE); 4666243791Sdim } 4667243791Sdim } 4668243791Sdim 4669243791Sdim return; 4670243791Sdim} 4671243791Sdim 4672263508Sdimvoid RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S, 4673263508Sdim SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs, 4674243791Sdim llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) { 4675243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 4676243791Sdim if (*CI) { 4677243791Sdim if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) { 4678243791Sdim InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl())); 4679243791Sdim GetInnerBlockDeclRefExprs(CBE->getBody(), 4680243791Sdim InnerBlockDeclRefs, 4681243791Sdim InnerContexts); 4682243791Sdim } 4683243791Sdim else 4684243791Sdim GetInnerBlockDeclRefExprs(*CI, 4685243791Sdim InnerBlockDeclRefs, 4686243791Sdim InnerContexts); 4687243791Sdim 4688243791Sdim } 4689243791Sdim // Handle specific things. 4690243791Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 4691243791Sdim if (DRE->refersToEnclosingLocal()) { 4692243791Sdim if (!isa<FunctionDecl>(DRE->getDecl()) && 4693243791Sdim !InnerContexts.count(DRE->getDecl()->getDeclContext())) 4694243791Sdim InnerBlockDeclRefs.push_back(DRE); 4695243791Sdim if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) 4696243791Sdim if (Var->isFunctionOrMethodVarDecl()) 4697243791Sdim ImportedLocalExternalDecls.insert(Var); 4698243791Sdim } 4699243791Sdim } 4700243791Sdim 4701243791Sdim return; 4702243791Sdim} 4703243791Sdim 4704243791Sdim/// convertObjCTypeToCStyleType - This routine converts such objc types 4705243791Sdim/// as qualified objects, and blocks to their closest c/c++ types that 4706243791Sdim/// it can. It returns true if input type was modified. 4707243791Sdimbool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) { 4708243791Sdim QualType oldT = T; 4709243791Sdim convertBlockPointerToFunctionPointer(T); 4710243791Sdim if (T->isFunctionPointerType()) { 4711243791Sdim QualType PointeeTy; 4712243791Sdim if (const PointerType* PT = T->getAs<PointerType>()) { 4713243791Sdim PointeeTy = PT->getPointeeType(); 4714243791Sdim if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) { 4715243791Sdim T = convertFunctionTypeOfBlocks(FT); 4716243791Sdim T = Context->getPointerType(T); 4717243791Sdim } 4718243791Sdim } 4719243791Sdim } 4720243791Sdim 4721243791Sdim convertToUnqualifiedObjCType(T); 4722243791Sdim return T != oldT; 4723243791Sdim} 4724243791Sdim 4725243791Sdim/// convertFunctionTypeOfBlocks - This routine converts a function type 4726243791Sdim/// whose result type may be a block pointer or whose argument type(s) 4727243791Sdim/// might be block pointers to an equivalent function type replacing 4728243791Sdim/// all block pointers to function pointers. 4729243791SdimQualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { 4730243791Sdim const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 4731243791Sdim // FTP will be null for closures that don't take arguments. 4732243791Sdim // Generate a funky cast. 4733243791Sdim SmallVector<QualType, 8> ArgTypes; 4734243791Sdim QualType Res = FT->getResultType(); 4735243791Sdim bool modified = convertObjCTypeToCStyleType(Res); 4736243791Sdim 4737243791Sdim if (FTP) { 4738243791Sdim for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 4739243791Sdim E = FTP->arg_type_end(); I && (I != E); ++I) { 4740243791Sdim QualType t = *I; 4741243791Sdim // Make sure we convert "t (^)(...)" to "t (*)(...)". 4742243791Sdim if (convertObjCTypeToCStyleType(t)) 4743243791Sdim modified = true; 4744243791Sdim ArgTypes.push_back(t); 4745243791Sdim } 4746243791Sdim } 4747243791Sdim QualType FuncType; 4748243791Sdim if (modified) 4749249423Sdim FuncType = getSimpleFunctionType(Res, ArgTypes); 4750243791Sdim else FuncType = QualType(FT, 0); 4751243791Sdim return FuncType; 4752243791Sdim} 4753243791Sdim 4754243791SdimStmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 4755243791Sdim // Navigate to relevant type information. 4756243791Sdim const BlockPointerType *CPT = 0; 4757243791Sdim 4758243791Sdim if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { 4759243791Sdim CPT = DRE->getType()->getAs<BlockPointerType>(); 4760243791Sdim } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { 4761243791Sdim CPT = MExpr->getType()->getAs<BlockPointerType>(); 4762243791Sdim } 4763243791Sdim else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) { 4764243791Sdim return SynthesizeBlockCall(Exp, PRE->getSubExpr()); 4765243791Sdim } 4766243791Sdim else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 4767243791Sdim CPT = IEXPR->getType()->getAs<BlockPointerType>(); 4768243791Sdim else if (const ConditionalOperator *CEXPR = 4769243791Sdim dyn_cast<ConditionalOperator>(BlockExp)) { 4770243791Sdim Expr *LHSExp = CEXPR->getLHS(); 4771243791Sdim Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp); 4772243791Sdim Expr *RHSExp = CEXPR->getRHS(); 4773243791Sdim Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); 4774243791Sdim Expr *CONDExp = CEXPR->getCond(); 4775243791Sdim ConditionalOperator *CondExpr = 4776243791Sdim new (Context) ConditionalOperator(CONDExp, 4777243791Sdim SourceLocation(), cast<Expr>(LHSStmt), 4778243791Sdim SourceLocation(), cast<Expr>(RHSStmt), 4779243791Sdim Exp->getType(), VK_RValue, OK_Ordinary); 4780243791Sdim return CondExpr; 4781243791Sdim } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { 4782243791Sdim CPT = IRE->getType()->getAs<BlockPointerType>(); 4783243791Sdim } else if (const PseudoObjectExpr *POE 4784243791Sdim = dyn_cast<PseudoObjectExpr>(BlockExp)) { 4785243791Sdim CPT = POE->getType()->castAs<BlockPointerType>(); 4786243791Sdim } else { 4787243791Sdim assert(1 && "RewriteBlockClass: Bad type"); 4788243791Sdim } 4789243791Sdim assert(CPT && "RewriteBlockClass: Bad type"); 4790243791Sdim const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); 4791243791Sdim assert(FT && "RewriteBlockClass: Bad type"); 4792243791Sdim const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 4793243791Sdim // FTP will be null for closures that don't take arguments. 4794243791Sdim 4795243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 4796243791Sdim SourceLocation(), SourceLocation(), 4797243791Sdim &Context->Idents.get("__block_impl")); 4798243791Sdim QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); 4799243791Sdim 4800243791Sdim // Generate a funky cast. 4801243791Sdim SmallVector<QualType, 8> ArgTypes; 4802243791Sdim 4803243791Sdim // Push the block argument type. 4804243791Sdim ArgTypes.push_back(PtrBlock); 4805243791Sdim if (FTP) { 4806243791Sdim for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 4807243791Sdim E = FTP->arg_type_end(); I && (I != E); ++I) { 4808243791Sdim QualType t = *I; 4809243791Sdim // Make sure we convert "t (^)(...)" to "t (*)(...)". 4810243791Sdim if (!convertBlockPointerToFunctionPointer(t)) 4811243791Sdim convertToUnqualifiedObjCType(t); 4812243791Sdim ArgTypes.push_back(t); 4813243791Sdim } 4814243791Sdim } 4815243791Sdim // Now do the pointer to function cast. 4816249423Sdim QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes); 4817243791Sdim 4818243791Sdim PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); 4819243791Sdim 4820243791Sdim CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock, 4821243791Sdim CK_BitCast, 4822243791Sdim const_cast<Expr*>(BlockExp)); 4823243791Sdim // Don't forget the parens to enforce the proper binding. 4824243791Sdim ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 4825243791Sdim BlkCast); 4826243791Sdim //PE->dump(); 4827243791Sdim 4828243791Sdim FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 4829243791Sdim SourceLocation(), 4830243791Sdim &Context->Idents.get("FuncPtr"), 4831243791Sdim Context->VoidPtrTy, 0, 4832243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 4833243791Sdim ICIS_NoInit); 4834243791Sdim MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 4835243791Sdim FD->getType(), VK_LValue, 4836243791Sdim OK_Ordinary); 4837243791Sdim 4838243791Sdim 4839243791Sdim CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, 4840243791Sdim CK_BitCast, ME); 4841243791Sdim PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); 4842243791Sdim 4843243791Sdim SmallVector<Expr*, 8> BlkExprs; 4844243791Sdim // Add the implicit argument. 4845243791Sdim BlkExprs.push_back(BlkCast); 4846243791Sdim // Add the user arguments. 4847243791Sdim for (CallExpr::arg_iterator I = Exp->arg_begin(), 4848243791Sdim E = Exp->arg_end(); I != E; ++I) { 4849243791Sdim BlkExprs.push_back(*I); 4850243791Sdim } 4851243791Sdim CallExpr *CE = new (Context) CallExpr(*Context, PE, BlkExprs, 4852243791Sdim Exp->getType(), VK_RValue, 4853243791Sdim SourceLocation()); 4854243791Sdim return CE; 4855243791Sdim} 4856243791Sdim 4857243791Sdim// We need to return the rewritten expression to handle cases where the 4858243791Sdim// DeclRefExpr is embedded in another expression being rewritten. 4859243791Sdim// For example: 4860243791Sdim// 4861243791Sdim// int main() { 4862243791Sdim// __block Foo *f; 4863243791Sdim// __block int i; 4864243791Sdim// 4865243791Sdim// void (^myblock)() = ^() { 4866243791Sdim// [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten). 4867243791Sdim// i = 77; 4868243791Sdim// }; 4869243791Sdim//} 4870243791SdimStmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { 4871243791Sdim // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 4872243791Sdim // for each DeclRefExp where BYREFVAR is name of the variable. 4873243791Sdim ValueDecl *VD = DeclRefExp->getDecl(); 4874243791Sdim bool isArrow = DeclRefExp->refersToEnclosingLocal(); 4875243791Sdim 4876243791Sdim FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 4877243791Sdim SourceLocation(), 4878243791Sdim &Context->Idents.get("__forwarding"), 4879243791Sdim Context->VoidPtrTy, 0, 4880243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 4881243791Sdim ICIS_NoInit); 4882243791Sdim MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow, 4883243791Sdim FD, SourceLocation(), 4884243791Sdim FD->getType(), VK_LValue, 4885243791Sdim OK_Ordinary); 4886243791Sdim 4887243791Sdim StringRef Name = VD->getName(); 4888243791Sdim FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 4889243791Sdim &Context->Idents.get(Name), 4890243791Sdim Context->VoidPtrTy, 0, 4891243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 4892243791Sdim ICIS_NoInit); 4893243791Sdim ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(), 4894243791Sdim DeclRefExp->getType(), VK_LValue, OK_Ordinary); 4895243791Sdim 4896243791Sdim 4897243791Sdim 4898243791Sdim // Need parens to enforce precedence. 4899243791Sdim ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 4900243791Sdim DeclRefExp->getExprLoc(), 4901243791Sdim ME); 4902243791Sdim ReplaceStmt(DeclRefExp, PE); 4903243791Sdim return PE; 4904243791Sdim} 4905243791Sdim 4906243791Sdim// Rewrites the imported local variable V with external storage 4907243791Sdim// (static, extern, etc.) as *V 4908243791Sdim// 4909243791SdimStmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { 4910243791Sdim ValueDecl *VD = DRE->getDecl(); 4911243791Sdim if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 4912243791Sdim if (!ImportedLocalExternalDecls.count(Var)) 4913243791Sdim return DRE; 4914243791Sdim Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), 4915243791Sdim VK_LValue, OK_Ordinary, 4916243791Sdim DRE->getLocation()); 4917243791Sdim // Need parens to enforce precedence. 4918243791Sdim ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 4919243791Sdim Exp); 4920243791Sdim ReplaceStmt(DRE, PE); 4921243791Sdim return PE; 4922243791Sdim} 4923243791Sdim 4924243791Sdimvoid RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) { 4925243791Sdim SourceLocation LocStart = CE->getLParenLoc(); 4926243791Sdim SourceLocation LocEnd = CE->getRParenLoc(); 4927243791Sdim 4928243791Sdim // Need to avoid trying to rewrite synthesized casts. 4929243791Sdim if (LocStart.isInvalid()) 4930243791Sdim return; 4931243791Sdim // Need to avoid trying to rewrite casts contained in macros. 4932243791Sdim if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) 4933243791Sdim return; 4934243791Sdim 4935243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 4936243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 4937243791Sdim QualType QT = CE->getType(); 4938243791Sdim const Type* TypePtr = QT->getAs<Type>(); 4939243791Sdim if (isa<TypeOfExprType>(TypePtr)) { 4940243791Sdim const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 4941243791Sdim QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 4942243791Sdim std::string TypeAsString = "("; 4943243791Sdim RewriteBlockPointerType(TypeAsString, QT); 4944243791Sdim TypeAsString += ")"; 4945243791Sdim ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); 4946243791Sdim return; 4947243791Sdim } 4948243791Sdim // advance the location to startArgList. 4949243791Sdim const char *argPtr = startBuf; 4950243791Sdim 4951243791Sdim while (*argPtr++ && (argPtr < endBuf)) { 4952243791Sdim switch (*argPtr) { 4953243791Sdim case '^': 4954243791Sdim // Replace the '^' with '*'. 4955243791Sdim LocStart = LocStart.getLocWithOffset(argPtr-startBuf); 4956243791Sdim ReplaceText(LocStart, 1, "*"); 4957243791Sdim break; 4958243791Sdim } 4959243791Sdim } 4960243791Sdim return; 4961243791Sdim} 4962243791Sdim 4963243791Sdimvoid RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) { 4964243791Sdim CastKind CastKind = IC->getCastKind(); 4965243791Sdim if (CastKind != CK_BlockPointerToObjCPointerCast && 4966243791Sdim CastKind != CK_AnyPointerToBlockPointerCast) 4967243791Sdim return; 4968243791Sdim 4969243791Sdim QualType QT = IC->getType(); 4970243791Sdim (void)convertBlockPointerToFunctionPointer(QT); 4971243791Sdim std::string TypeString(QT.getAsString(Context->getPrintingPolicy())); 4972243791Sdim std::string Str = "("; 4973243791Sdim Str += TypeString; 4974243791Sdim Str += ")"; 4975243791Sdim InsertText(IC->getSubExpr()->getLocStart(), &Str[0], Str.size()); 4976243791Sdim 4977243791Sdim return; 4978243791Sdim} 4979243791Sdim 4980243791Sdimvoid RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { 4981243791Sdim SourceLocation DeclLoc = FD->getLocation(); 4982243791Sdim unsigned parenCount = 0; 4983243791Sdim 4984243791Sdim // We have 1 or more arguments that have closure pointers. 4985243791Sdim const char *startBuf = SM->getCharacterData(DeclLoc); 4986243791Sdim const char *startArgList = strchr(startBuf, '('); 4987243791Sdim 4988243791Sdim assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); 4989243791Sdim 4990243791Sdim parenCount++; 4991243791Sdim // advance the location to startArgList. 4992243791Sdim DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf); 4993243791Sdim assert((DeclLoc.isValid()) && "Invalid DeclLoc"); 4994243791Sdim 4995243791Sdim const char *argPtr = startArgList; 4996243791Sdim 4997243791Sdim while (*argPtr++ && parenCount) { 4998243791Sdim switch (*argPtr) { 4999243791Sdim case '^': 5000243791Sdim // Replace the '^' with '*'. 5001243791Sdim DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList); 5002243791Sdim ReplaceText(DeclLoc, 1, "*"); 5003243791Sdim break; 5004243791Sdim case '(': 5005243791Sdim parenCount++; 5006243791Sdim break; 5007243791Sdim case ')': 5008243791Sdim parenCount--; 5009243791Sdim break; 5010243791Sdim } 5011243791Sdim } 5012243791Sdim return; 5013243791Sdim} 5014243791Sdim 5015243791Sdimbool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { 5016243791Sdim const FunctionProtoType *FTP; 5017243791Sdim const PointerType *PT = QT->getAs<PointerType>(); 5018243791Sdim if (PT) { 5019243791Sdim FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 5020243791Sdim } else { 5021243791Sdim const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 5022243791Sdim assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 5023243791Sdim FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 5024243791Sdim } 5025243791Sdim if (FTP) { 5026243791Sdim for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 5027243791Sdim E = FTP->arg_type_end(); I != E; ++I) 5028243791Sdim if (isTopLevelBlockPointerType(*I)) 5029243791Sdim return true; 5030243791Sdim } 5031243791Sdim return false; 5032243791Sdim} 5033243791Sdim 5034243791Sdimbool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) { 5035243791Sdim const FunctionProtoType *FTP; 5036243791Sdim const PointerType *PT = QT->getAs<PointerType>(); 5037243791Sdim if (PT) { 5038243791Sdim FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 5039243791Sdim } else { 5040243791Sdim const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 5041243791Sdim assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 5042243791Sdim FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 5043243791Sdim } 5044243791Sdim if (FTP) { 5045243791Sdim for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 5046243791Sdim E = FTP->arg_type_end(); I != E; ++I) { 5047243791Sdim if ((*I)->isObjCQualifiedIdType()) 5048243791Sdim return true; 5049243791Sdim if ((*I)->isObjCObjectPointerType() && 5050243791Sdim (*I)->getPointeeType()->isObjCQualifiedInterfaceType()) 5051243791Sdim return true; 5052243791Sdim } 5053243791Sdim 5054243791Sdim } 5055243791Sdim return false; 5056243791Sdim} 5057243791Sdim 5058243791Sdimvoid RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen, 5059243791Sdim const char *&RParen) { 5060243791Sdim const char *argPtr = strchr(Name, '('); 5061243791Sdim assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); 5062243791Sdim 5063243791Sdim LParen = argPtr; // output the start. 5064243791Sdim argPtr++; // skip past the left paren. 5065243791Sdim unsigned parenCount = 1; 5066243791Sdim 5067243791Sdim while (*argPtr && parenCount) { 5068243791Sdim switch (*argPtr) { 5069243791Sdim case '(': parenCount++; break; 5070243791Sdim case ')': parenCount--; break; 5071243791Sdim default: break; 5072243791Sdim } 5073243791Sdim if (parenCount) argPtr++; 5074243791Sdim } 5075243791Sdim assert((*argPtr == ')') && "Rewriter fuzzy parser confused"); 5076243791Sdim RParen = argPtr; // output the end 5077243791Sdim} 5078243791Sdim 5079243791Sdimvoid RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) { 5080243791Sdim if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 5081243791Sdim RewriteBlockPointerFunctionArgs(FD); 5082243791Sdim return; 5083243791Sdim } 5084243791Sdim // Handle Variables and Typedefs. 5085243791Sdim SourceLocation DeclLoc = ND->getLocation(); 5086243791Sdim QualType DeclT; 5087243791Sdim if (VarDecl *VD = dyn_cast<VarDecl>(ND)) 5088243791Sdim DeclT = VD->getType(); 5089243791Sdim else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND)) 5090243791Sdim DeclT = TDD->getUnderlyingType(); 5091243791Sdim else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) 5092243791Sdim DeclT = FD->getType(); 5093243791Sdim else 5094243791Sdim llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled"); 5095243791Sdim 5096243791Sdim const char *startBuf = SM->getCharacterData(DeclLoc); 5097243791Sdim const char *endBuf = startBuf; 5098243791Sdim // scan backward (from the decl location) for the end of the previous decl. 5099243791Sdim while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) 5100243791Sdim startBuf--; 5101243791Sdim SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf); 5102243791Sdim std::string buf; 5103243791Sdim unsigned OrigLength=0; 5104243791Sdim // *startBuf != '^' if we are dealing with a pointer to function that 5105243791Sdim // may take block argument types (which will be handled below). 5106243791Sdim if (*startBuf == '^') { 5107243791Sdim // Replace the '^' with '*', computing a negative offset. 5108243791Sdim buf = '*'; 5109243791Sdim startBuf++; 5110243791Sdim OrigLength++; 5111243791Sdim } 5112243791Sdim while (*startBuf != ')') { 5113243791Sdim buf += *startBuf; 5114243791Sdim startBuf++; 5115243791Sdim OrigLength++; 5116243791Sdim } 5117243791Sdim buf += ')'; 5118243791Sdim OrigLength++; 5119243791Sdim 5120243791Sdim if (PointerTypeTakesAnyBlockArguments(DeclT) || 5121243791Sdim PointerTypeTakesAnyObjCQualifiedType(DeclT)) { 5122243791Sdim // Replace the '^' with '*' for arguments. 5123243791Sdim // Replace id<P> with id/*<>*/ 5124243791Sdim DeclLoc = ND->getLocation(); 5125243791Sdim startBuf = SM->getCharacterData(DeclLoc); 5126243791Sdim const char *argListBegin, *argListEnd; 5127243791Sdim GetExtentOfArgList(startBuf, argListBegin, argListEnd); 5128243791Sdim while (argListBegin < argListEnd) { 5129243791Sdim if (*argListBegin == '^') 5130243791Sdim buf += '*'; 5131243791Sdim else if (*argListBegin == '<') { 5132243791Sdim buf += "/*"; 5133243791Sdim buf += *argListBegin++; 5134243791Sdim OrigLength++; 5135243791Sdim while (*argListBegin != '>') { 5136243791Sdim buf += *argListBegin++; 5137243791Sdim OrigLength++; 5138243791Sdim } 5139243791Sdim buf += *argListBegin; 5140243791Sdim buf += "*/"; 5141243791Sdim } 5142243791Sdim else 5143243791Sdim buf += *argListBegin; 5144243791Sdim argListBegin++; 5145243791Sdim OrigLength++; 5146243791Sdim } 5147243791Sdim buf += ')'; 5148243791Sdim OrigLength++; 5149243791Sdim } 5150243791Sdim ReplaceText(Start, OrigLength, buf); 5151243791Sdim 5152243791Sdim return; 5153243791Sdim} 5154243791Sdim 5155243791Sdim 5156243791Sdim/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: 5157243791Sdim/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, 5158243791Sdim/// struct Block_byref_id_object *src) { 5159243791Sdim/// _Block_object_assign (&_dest->object, _src->object, 5160243791Sdim/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 5161243791Sdim/// [|BLOCK_FIELD_IS_WEAK]) // object 5162243791Sdim/// _Block_object_assign(&_dest->object, _src->object, 5163243791Sdim/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 5164243791Sdim/// [|BLOCK_FIELD_IS_WEAK]) // block 5165243791Sdim/// } 5166243791Sdim/// And: 5167243791Sdim/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { 5168243791Sdim/// _Block_object_dispose(_src->object, 5169243791Sdim/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 5170243791Sdim/// [|BLOCK_FIELD_IS_WEAK]) // object 5171243791Sdim/// _Block_object_dispose(_src->object, 5172243791Sdim/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 5173243791Sdim/// [|BLOCK_FIELD_IS_WEAK]) // block 5174243791Sdim/// } 5175243791Sdim 5176243791Sdimstd::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, 5177243791Sdim int flag) { 5178243791Sdim std::string S; 5179243791Sdim if (CopyDestroyCache.count(flag)) 5180243791Sdim return S; 5181243791Sdim CopyDestroyCache.insert(flag); 5182243791Sdim S = "static void __Block_byref_id_object_copy_"; 5183243791Sdim S += utostr(flag); 5184243791Sdim S += "(void *dst, void *src) {\n"; 5185243791Sdim 5186243791Sdim // offset into the object pointer is computed as: 5187243791Sdim // void * + void* + int + int + void* + void * 5188243791Sdim unsigned IntSize = 5189243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 5190243791Sdim unsigned VoidPtrSize = 5191243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); 5192243791Sdim 5193243791Sdim unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth(); 5194243791Sdim S += " _Block_object_assign((char*)dst + "; 5195243791Sdim S += utostr(offset); 5196243791Sdim S += ", *(void * *) ((char*)src + "; 5197243791Sdim S += utostr(offset); 5198243791Sdim S += "), "; 5199243791Sdim S += utostr(flag); 5200243791Sdim S += ");\n}\n"; 5201243791Sdim 5202243791Sdim S += "static void __Block_byref_id_object_dispose_"; 5203243791Sdim S += utostr(flag); 5204243791Sdim S += "(void *src) {\n"; 5205243791Sdim S += " _Block_object_dispose(*(void * *) ((char*)src + "; 5206243791Sdim S += utostr(offset); 5207243791Sdim S += "), "; 5208243791Sdim S += utostr(flag); 5209243791Sdim S += ");\n}\n"; 5210243791Sdim return S; 5211243791Sdim} 5212243791Sdim 5213243791Sdim/// RewriteByRefVar - For each __block typex ND variable this routine transforms 5214243791Sdim/// the declaration into: 5215243791Sdim/// struct __Block_byref_ND { 5216243791Sdim/// void *__isa; // NULL for everything except __weak pointers 5217243791Sdim/// struct __Block_byref_ND *__forwarding; 5218243791Sdim/// int32_t __flags; 5219243791Sdim/// int32_t __size; 5220243791Sdim/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object 5221243791Sdim/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object 5222243791Sdim/// typex ND; 5223243791Sdim/// }; 5224243791Sdim/// 5225243791Sdim/// It then replaces declaration of ND variable with: 5226243791Sdim/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 5227243791Sdim/// __size=sizeof(struct __Block_byref_ND), 5228243791Sdim/// ND=initializer-if-any}; 5229243791Sdim/// 5230243791Sdim/// 5231243791Sdimvoid RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl, 5232243791Sdim bool lastDecl) { 5233243791Sdim int flag = 0; 5234243791Sdim int isa = 0; 5235243791Sdim SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 5236243791Sdim if (DeclLoc.isInvalid()) 5237243791Sdim // If type location is missing, it is because of missing type (a warning). 5238243791Sdim // Use variable's location which is good for this case. 5239243791Sdim DeclLoc = ND->getLocation(); 5240243791Sdim const char *startBuf = SM->getCharacterData(DeclLoc); 5241243791Sdim SourceLocation X = ND->getLocEnd(); 5242243791Sdim X = SM->getExpansionLoc(X); 5243243791Sdim const char *endBuf = SM->getCharacterData(X); 5244243791Sdim std::string Name(ND->getNameAsString()); 5245243791Sdim std::string ByrefType; 5246243791Sdim RewriteByRefString(ByrefType, Name, ND, true); 5247243791Sdim ByrefType += " {\n"; 5248243791Sdim ByrefType += " void *__isa;\n"; 5249243791Sdim RewriteByRefString(ByrefType, Name, ND); 5250243791Sdim ByrefType += " *__forwarding;\n"; 5251243791Sdim ByrefType += " int __flags;\n"; 5252243791Sdim ByrefType += " int __size;\n"; 5253243791Sdim // Add void *__Block_byref_id_object_copy; 5254243791Sdim // void *__Block_byref_id_object_dispose; if needed. 5255243791Sdim QualType Ty = ND->getType(); 5256249423Sdim bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND); 5257243791Sdim if (HasCopyAndDispose) { 5258243791Sdim ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; 5259243791Sdim ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; 5260243791Sdim } 5261243791Sdim 5262243791Sdim QualType T = Ty; 5263243791Sdim (void)convertBlockPointerToFunctionPointer(T); 5264243791Sdim T.getAsStringInternal(Name, Context->getPrintingPolicy()); 5265243791Sdim 5266243791Sdim ByrefType += " " + Name + ";\n"; 5267243791Sdim ByrefType += "};\n"; 5268243791Sdim // Insert this type in global scope. It is needed by helper function. 5269243791Sdim SourceLocation FunLocStart; 5270243791Sdim if (CurFunctionDef) 5271243791Sdim FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef); 5272243791Sdim else { 5273243791Sdim assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); 5274243791Sdim FunLocStart = CurMethodDef->getLocStart(); 5275243791Sdim } 5276243791Sdim InsertText(FunLocStart, ByrefType); 5277243791Sdim 5278243791Sdim if (Ty.isObjCGCWeak()) { 5279243791Sdim flag |= BLOCK_FIELD_IS_WEAK; 5280243791Sdim isa = 1; 5281243791Sdim } 5282243791Sdim if (HasCopyAndDispose) { 5283243791Sdim flag = BLOCK_BYREF_CALLER; 5284243791Sdim QualType Ty = ND->getType(); 5285243791Sdim // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. 5286243791Sdim if (Ty->isBlockPointerType()) 5287243791Sdim flag |= BLOCK_FIELD_IS_BLOCK; 5288243791Sdim else 5289243791Sdim flag |= BLOCK_FIELD_IS_OBJECT; 5290243791Sdim std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); 5291243791Sdim if (!HF.empty()) 5292249423Sdim Preamble += HF; 5293243791Sdim } 5294243791Sdim 5295243791Sdim // struct __Block_byref_ND ND = 5296243791Sdim // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 5297243791Sdim // initializer-if-any}; 5298243791Sdim bool hasInit = (ND->getInit() != 0); 5299243791Sdim // FIXME. rewriter does not support __block c++ objects which 5300243791Sdim // require construction. 5301243791Sdim if (hasInit) 5302243791Sdim if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) { 5303243791Sdim CXXConstructorDecl *CXXDecl = CExp->getConstructor(); 5304243791Sdim if (CXXDecl && CXXDecl->isDefaultConstructor()) 5305243791Sdim hasInit = false; 5306243791Sdim } 5307243791Sdim 5308243791Sdim unsigned flags = 0; 5309243791Sdim if (HasCopyAndDispose) 5310243791Sdim flags |= BLOCK_HAS_COPY_DISPOSE; 5311243791Sdim Name = ND->getNameAsString(); 5312243791Sdim ByrefType.clear(); 5313243791Sdim RewriteByRefString(ByrefType, Name, ND); 5314243791Sdim std::string ForwardingCastType("("); 5315243791Sdim ForwardingCastType += ByrefType + " *)"; 5316243791Sdim ByrefType += " " + Name + " = {(void*)"; 5317243791Sdim ByrefType += utostr(isa); 5318243791Sdim ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 5319243791Sdim ByrefType += utostr(flags); 5320243791Sdim ByrefType += ", "; 5321243791Sdim ByrefType += "sizeof("; 5322243791Sdim RewriteByRefString(ByrefType, Name, ND); 5323243791Sdim ByrefType += ")"; 5324243791Sdim if (HasCopyAndDispose) { 5325243791Sdim ByrefType += ", __Block_byref_id_object_copy_"; 5326243791Sdim ByrefType += utostr(flag); 5327243791Sdim ByrefType += ", __Block_byref_id_object_dispose_"; 5328243791Sdim ByrefType += utostr(flag); 5329243791Sdim } 5330243791Sdim 5331243791Sdim if (!firstDecl) { 5332243791Sdim // In multiple __block declarations, and for all but 1st declaration, 5333243791Sdim // find location of the separating comma. This would be start location 5334243791Sdim // where new text is to be inserted. 5335243791Sdim DeclLoc = ND->getLocation(); 5336243791Sdim const char *startDeclBuf = SM->getCharacterData(DeclLoc); 5337243791Sdim const char *commaBuf = startDeclBuf; 5338243791Sdim while (*commaBuf != ',') 5339243791Sdim commaBuf--; 5340243791Sdim assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','"); 5341243791Sdim DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf); 5342243791Sdim startBuf = commaBuf; 5343243791Sdim } 5344243791Sdim 5345243791Sdim if (!hasInit) { 5346243791Sdim ByrefType += "};\n"; 5347243791Sdim unsigned nameSize = Name.size(); 5348243791Sdim // for block or function pointer declaration. Name is aleady 5349243791Sdim // part of the declaration. 5350243791Sdim if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) 5351243791Sdim nameSize = 1; 5352243791Sdim ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType); 5353243791Sdim } 5354243791Sdim else { 5355243791Sdim ByrefType += ", "; 5356243791Sdim SourceLocation startLoc; 5357243791Sdim Expr *E = ND->getInit(); 5358243791Sdim if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 5359243791Sdim startLoc = ECE->getLParenLoc(); 5360243791Sdim else 5361243791Sdim startLoc = E->getLocStart(); 5362243791Sdim startLoc = SM->getExpansionLoc(startLoc); 5363243791Sdim endBuf = SM->getCharacterData(startLoc); 5364243791Sdim ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); 5365243791Sdim 5366243791Sdim const char separator = lastDecl ? ';' : ','; 5367243791Sdim const char *startInitializerBuf = SM->getCharacterData(startLoc); 5368243791Sdim const char *separatorBuf = strchr(startInitializerBuf, separator); 5369243791Sdim assert((*separatorBuf == separator) && 5370243791Sdim "RewriteByRefVar: can't find ';' or ','"); 5371243791Sdim SourceLocation separatorLoc = 5372243791Sdim startLoc.getLocWithOffset(separatorBuf-startInitializerBuf); 5373243791Sdim 5374243791Sdim InsertText(separatorLoc, lastDecl ? "}" : "};\n"); 5375243791Sdim } 5376243791Sdim return; 5377243791Sdim} 5378243791Sdim 5379243791Sdimvoid RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { 5380243791Sdim // Add initializers for any closure decl refs. 5381243791Sdim GetBlockDeclRefExprs(Exp->getBody()); 5382243791Sdim if (BlockDeclRefs.size()) { 5383243791Sdim // Unique all "by copy" declarations. 5384243791Sdim for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 5385243791Sdim if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 5386243791Sdim if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 5387243791Sdim BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 5388243791Sdim BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); 5389243791Sdim } 5390243791Sdim } 5391243791Sdim // Unique all "by ref" declarations. 5392243791Sdim for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 5393243791Sdim if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 5394243791Sdim if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 5395243791Sdim BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 5396243791Sdim BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); 5397243791Sdim } 5398243791Sdim } 5399243791Sdim // Find any imported blocks...they will need special attention. 5400243791Sdim for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 5401243791Sdim if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 5402243791Sdim BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 5403243791Sdim BlockDeclRefs[i]->getType()->isBlockPointerType()) 5404243791Sdim ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); 5405243791Sdim } 5406243791Sdim} 5407243791Sdim 5408243791SdimFunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) { 5409243791Sdim IdentifierInfo *ID = &Context->Idents.get(name); 5410243791Sdim QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); 5411243791Sdim return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), 5412243791Sdim SourceLocation(), ID, FType, 0, SC_Extern, 5413249423Sdim false, false); 5414243791Sdim} 5415243791Sdim 5416243791SdimStmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, 5417263508Sdim const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) { 5418243791Sdim 5419243791Sdim const BlockDecl *block = Exp->getBlockDecl(); 5420243791Sdim 5421243791Sdim Blocks.push_back(Exp); 5422243791Sdim 5423243791Sdim CollectBlockDeclRefInfo(Exp); 5424243791Sdim 5425243791Sdim // Add inner imported variables now used in current block. 5426243791Sdim int countOfInnerDecls = 0; 5427243791Sdim if (!InnerBlockDeclRefs.empty()) { 5428243791Sdim for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { 5429243791Sdim DeclRefExpr *Exp = InnerBlockDeclRefs[i]; 5430243791Sdim ValueDecl *VD = Exp->getDecl(); 5431243791Sdim if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { 5432243791Sdim // We need to save the copied-in variables in nested 5433243791Sdim // blocks because it is needed at the end for some of the API generations. 5434243791Sdim // See SynthesizeBlockLiterals routine. 5435243791Sdim InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 5436243791Sdim BlockDeclRefs.push_back(Exp); 5437243791Sdim BlockByCopyDeclsPtrSet.insert(VD); 5438243791Sdim BlockByCopyDecls.push_back(VD); 5439243791Sdim } 5440243791Sdim if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { 5441243791Sdim InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 5442243791Sdim BlockDeclRefs.push_back(Exp); 5443243791Sdim BlockByRefDeclsPtrSet.insert(VD); 5444243791Sdim BlockByRefDecls.push_back(VD); 5445243791Sdim } 5446243791Sdim } 5447243791Sdim // Find any imported blocks...they will need special attention. 5448243791Sdim for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) 5449243791Sdim if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 5450243791Sdim InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 5451243791Sdim InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) 5452243791Sdim ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); 5453243791Sdim } 5454243791Sdim InnerDeclRefsCount.push_back(countOfInnerDecls); 5455243791Sdim 5456243791Sdim std::string FuncName; 5457243791Sdim 5458243791Sdim if (CurFunctionDef) 5459243791Sdim FuncName = CurFunctionDef->getNameAsString(); 5460243791Sdim else if (CurMethodDef) 5461243791Sdim BuildUniqueMethodName(FuncName, CurMethodDef); 5462243791Sdim else if (GlobalVarDecl) 5463243791Sdim FuncName = std::string(GlobalVarDecl->getNameAsString()); 5464243791Sdim 5465243791Sdim bool GlobalBlockExpr = 5466243791Sdim block->getDeclContext()->getRedeclContext()->isFileContext(); 5467243791Sdim 5468243791Sdim if (GlobalBlockExpr && !GlobalVarDecl) { 5469243791Sdim Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag); 5470243791Sdim GlobalBlockExpr = false; 5471243791Sdim } 5472243791Sdim 5473243791Sdim std::string BlockNumber = utostr(Blocks.size()-1); 5474243791Sdim 5475243791Sdim std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; 5476243791Sdim 5477243791Sdim // Get a pointer to the function type so we can cast appropriately. 5478243791Sdim QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType()); 5479243791Sdim QualType FType = Context->getPointerType(BFT); 5480243791Sdim 5481243791Sdim FunctionDecl *FD; 5482243791Sdim Expr *NewRep; 5483243791Sdim 5484263508Sdim // Simulate a constructor call... 5485243791Sdim std::string Tag; 5486243791Sdim 5487243791Sdim if (GlobalBlockExpr) 5488243791Sdim Tag = "__global_"; 5489243791Sdim else 5490243791Sdim Tag = "__"; 5491243791Sdim Tag += FuncName + "_block_impl_" + BlockNumber; 5492243791Sdim 5493243791Sdim FD = SynthBlockInitFunctionDecl(Tag); 5494243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue, 5495243791Sdim SourceLocation()); 5496243791Sdim 5497243791Sdim SmallVector<Expr*, 4> InitExprs; 5498243791Sdim 5499243791Sdim // Initialize the block function. 5500243791Sdim FD = SynthBlockInitFunctionDecl(Func); 5501243791Sdim DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), 5502243791Sdim VK_LValue, SourceLocation()); 5503243791Sdim CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 5504243791Sdim CK_BitCast, Arg); 5505243791Sdim InitExprs.push_back(castExpr); 5506243791Sdim 5507243791Sdim // Initialize the block descriptor. 5508243791Sdim std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; 5509243791Sdim 5510243791Sdim VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, 5511243791Sdim SourceLocation(), SourceLocation(), 5512243791Sdim &Context->Idents.get(DescData.c_str()), 5513243791Sdim Context->VoidPtrTy, 0, 5514249423Sdim SC_Static); 5515243791Sdim UnaryOperator *DescRefExpr = 5516243791Sdim new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false, 5517243791Sdim Context->VoidPtrTy, 5518243791Sdim VK_LValue, 5519243791Sdim SourceLocation()), 5520243791Sdim UO_AddrOf, 5521243791Sdim Context->getPointerType(Context->VoidPtrTy), 5522243791Sdim VK_RValue, OK_Ordinary, 5523243791Sdim SourceLocation()); 5524243791Sdim InitExprs.push_back(DescRefExpr); 5525243791Sdim 5526243791Sdim // Add initializers for any closure decl refs. 5527243791Sdim if (BlockDeclRefs.size()) { 5528243791Sdim Expr *Exp; 5529243791Sdim // Output all "by copy" declarations. 5530263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 5531243791Sdim E = BlockByCopyDecls.end(); I != E; ++I) { 5532243791Sdim if (isObjCType((*I)->getType())) { 5533243791Sdim // FIXME: Conform to ABI ([[obj retain] autorelease]). 5534243791Sdim FD = SynthBlockInitFunctionDecl((*I)->getName()); 5535243791Sdim Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), 5536243791Sdim VK_LValue, SourceLocation()); 5537243791Sdim if (HasLocalVariableExternalStorage(*I)) { 5538243791Sdim QualType QT = (*I)->getType(); 5539243791Sdim QT = Context->getPointerType(QT); 5540243791Sdim Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 5541243791Sdim OK_Ordinary, SourceLocation()); 5542243791Sdim } 5543243791Sdim } else if (isTopLevelBlockPointerType((*I)->getType())) { 5544243791Sdim FD = SynthBlockInitFunctionDecl((*I)->getName()); 5545243791Sdim Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), 5546243791Sdim VK_LValue, SourceLocation()); 5547243791Sdim Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 5548243791Sdim CK_BitCast, Arg); 5549243791Sdim } else { 5550243791Sdim FD = SynthBlockInitFunctionDecl((*I)->getName()); 5551243791Sdim Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), 5552243791Sdim VK_LValue, SourceLocation()); 5553243791Sdim if (HasLocalVariableExternalStorage(*I)) { 5554243791Sdim QualType QT = (*I)->getType(); 5555243791Sdim QT = Context->getPointerType(QT); 5556243791Sdim Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 5557243791Sdim OK_Ordinary, SourceLocation()); 5558243791Sdim } 5559243791Sdim 5560243791Sdim } 5561243791Sdim InitExprs.push_back(Exp); 5562243791Sdim } 5563243791Sdim // Output all "by ref" declarations. 5564263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 5565243791Sdim E = BlockByRefDecls.end(); I != E; ++I) { 5566243791Sdim ValueDecl *ND = (*I); 5567243791Sdim std::string Name(ND->getNameAsString()); 5568243791Sdim std::string RecName; 5569243791Sdim RewriteByRefString(RecName, Name, ND, true); 5570243791Sdim IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 5571243791Sdim + sizeof("struct")); 5572243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 5573243791Sdim SourceLocation(), SourceLocation(), 5574243791Sdim II); 5575243791Sdim assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); 5576243791Sdim QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 5577243791Sdim 5578243791Sdim FD = SynthBlockInitFunctionDecl((*I)->getName()); 5579243791Sdim Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, 5580243791Sdim SourceLocation()); 5581243791Sdim bool isNestedCapturedVar = false; 5582243791Sdim if (block) 5583243791Sdim for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 5584243791Sdim ce = block->capture_end(); ci != ce; ++ci) { 5585243791Sdim const VarDecl *variable = ci->getVariable(); 5586243791Sdim if (variable == ND && ci->isNested()) { 5587243791Sdim assert (ci->isByRef() && 5588243791Sdim "SynthBlockInitExpr - captured block variable is not byref"); 5589243791Sdim isNestedCapturedVar = true; 5590243791Sdim break; 5591243791Sdim } 5592243791Sdim } 5593243791Sdim // captured nested byref variable has its address passed. Do not take 5594243791Sdim // its address again. 5595243791Sdim if (!isNestedCapturedVar) 5596243791Sdim Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, 5597243791Sdim Context->getPointerType(Exp->getType()), 5598243791Sdim VK_RValue, OK_Ordinary, SourceLocation()); 5599243791Sdim Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); 5600243791Sdim InitExprs.push_back(Exp); 5601243791Sdim } 5602243791Sdim } 5603243791Sdim if (ImportedBlockDecls.size()) { 5604243791Sdim // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR 5605243791Sdim int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR); 5606243791Sdim unsigned IntSize = 5607243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 5608243791Sdim Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 5609243791Sdim Context->IntTy, SourceLocation()); 5610243791Sdim InitExprs.push_back(FlagExp); 5611243791Sdim } 5612243791Sdim NewRep = new (Context) CallExpr(*Context, DRE, InitExprs, 5613243791Sdim FType, VK_LValue, SourceLocation()); 5614243791Sdim 5615243791Sdim if (GlobalBlockExpr) { 5616243791Sdim assert (GlobalConstructionExp == 0 && 5617243791Sdim "SynthBlockInitExpr - GlobalConstructionExp must be null"); 5618243791Sdim GlobalConstructionExp = NewRep; 5619243791Sdim NewRep = DRE; 5620243791Sdim } 5621243791Sdim 5622243791Sdim NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, 5623243791Sdim Context->getPointerType(NewRep->getType()), 5624243791Sdim VK_RValue, OK_Ordinary, SourceLocation()); 5625243791Sdim NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, 5626243791Sdim NewRep); 5627243791Sdim BlockDeclRefs.clear(); 5628243791Sdim BlockByRefDecls.clear(); 5629243791Sdim BlockByRefDeclsPtrSet.clear(); 5630243791Sdim BlockByCopyDecls.clear(); 5631243791Sdim BlockByCopyDeclsPtrSet.clear(); 5632243791Sdim ImportedBlockDecls.clear(); 5633243791Sdim return NewRep; 5634243791Sdim} 5635243791Sdim 5636243791Sdimbool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { 5637243791Sdim if (const ObjCForCollectionStmt * CS = 5638243791Sdim dyn_cast<ObjCForCollectionStmt>(Stmts.back())) 5639243791Sdim return CS->getElement() == DS; 5640243791Sdim return false; 5641243791Sdim} 5642243791Sdim 5643243791Sdim//===----------------------------------------------------------------------===// 5644243791Sdim// Function Body / Expression rewriting 5645243791Sdim//===----------------------------------------------------------------------===// 5646243791Sdim 5647243791SdimStmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { 5648243791Sdim if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 5649243791Sdim isa<DoStmt>(S) || isa<ForStmt>(S)) 5650243791Sdim Stmts.push_back(S); 5651243791Sdim else if (isa<ObjCForCollectionStmt>(S)) { 5652243791Sdim Stmts.push_back(S); 5653243791Sdim ObjCBcLabelNo.push_back(++BcLabelCount); 5654243791Sdim } 5655243791Sdim 5656243791Sdim // Pseudo-object operations and ivar references need special 5657243791Sdim // treatment because we're going to recursively rewrite them. 5658243791Sdim if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) { 5659243791Sdim if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) { 5660243791Sdim return RewritePropertyOrImplicitSetter(PseudoOp); 5661243791Sdim } else { 5662243791Sdim return RewritePropertyOrImplicitGetter(PseudoOp); 5663243791Sdim } 5664243791Sdim } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 5665243791Sdim return RewriteObjCIvarRefExpr(IvarRefExpr); 5666243791Sdim } 5667249423Sdim else if (isa<OpaqueValueExpr>(S)) 5668249423Sdim S = cast<OpaqueValueExpr>(S)->getSourceExpr(); 5669243791Sdim 5670243791Sdim SourceRange OrigStmtRange = S->getSourceRange(); 5671243791Sdim 5672243791Sdim // Perform a bottom up rewrite of all children. 5673243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 5674243791Sdim if (*CI) { 5675243791Sdim Stmt *childStmt = (*CI); 5676243791Sdim Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt); 5677243791Sdim if (newStmt) { 5678243791Sdim *CI = newStmt; 5679243791Sdim } 5680243791Sdim } 5681243791Sdim 5682243791Sdim if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { 5683243791Sdim SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs; 5684243791Sdim llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; 5685243791Sdim InnerContexts.insert(BE->getBlockDecl()); 5686243791Sdim ImportedLocalExternalDecls.clear(); 5687243791Sdim GetInnerBlockDeclRefExprs(BE->getBody(), 5688243791Sdim InnerBlockDeclRefs, InnerContexts); 5689243791Sdim // Rewrite the block body in place. 5690243791Sdim Stmt *SaveCurrentBody = CurrentBody; 5691243791Sdim CurrentBody = BE->getBody(); 5692243791Sdim PropParentMap = 0; 5693243791Sdim // block literal on rhs of a property-dot-sytax assignment 5694243791Sdim // must be replaced by its synthesize ast so getRewrittenText 5695243791Sdim // works as expected. In this case, what actually ends up on RHS 5696243791Sdim // is the blockTranscribed which is the helper function for the 5697243791Sdim // block literal; as in: self.c = ^() {[ace ARR];}; 5698243791Sdim bool saveDisableReplaceStmt = DisableReplaceStmt; 5699243791Sdim DisableReplaceStmt = false; 5700243791Sdim RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); 5701243791Sdim DisableReplaceStmt = saveDisableReplaceStmt; 5702243791Sdim CurrentBody = SaveCurrentBody; 5703243791Sdim PropParentMap = 0; 5704243791Sdim ImportedLocalExternalDecls.clear(); 5705243791Sdim // Now we snarf the rewritten text and stash it away for later use. 5706243791Sdim std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); 5707243791Sdim RewrittenBlockExprs[BE] = Str; 5708243791Sdim 5709243791Sdim Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); 5710243791Sdim 5711243791Sdim //blockTranscribed->dump(); 5712243791Sdim ReplaceStmt(S, blockTranscribed); 5713243791Sdim return blockTranscribed; 5714243791Sdim } 5715243791Sdim // Handle specific things. 5716243791Sdim if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) 5717243791Sdim return RewriteAtEncode(AtEncode); 5718243791Sdim 5719243791Sdim if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) 5720243791Sdim return RewriteAtSelector(AtSelector); 5721243791Sdim 5722243791Sdim if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) 5723243791Sdim return RewriteObjCStringLiteral(AtString); 5724243791Sdim 5725243791Sdim if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S)) 5726243791Sdim return RewriteObjCBoolLiteralExpr(BoolLitExpr); 5727243791Sdim 5728243791Sdim if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S)) 5729243791Sdim return RewriteObjCBoxedExpr(BoxedExpr); 5730243791Sdim 5731243791Sdim if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S)) 5732243791Sdim return RewriteObjCArrayLiteralExpr(ArrayLitExpr); 5733243791Sdim 5734243791Sdim if (ObjCDictionaryLiteral *DictionaryLitExpr = 5735243791Sdim dyn_cast<ObjCDictionaryLiteral>(S)) 5736243791Sdim return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr); 5737243791Sdim 5738243791Sdim if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { 5739243791Sdim#if 0 5740243791Sdim // Before we rewrite it, put the original message expression in a comment. 5741243791Sdim SourceLocation startLoc = MessExpr->getLocStart(); 5742243791Sdim SourceLocation endLoc = MessExpr->getLocEnd(); 5743243791Sdim 5744243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 5745243791Sdim const char *endBuf = SM->getCharacterData(endLoc); 5746243791Sdim 5747243791Sdim std::string messString; 5748243791Sdim messString += "// "; 5749243791Sdim messString.append(startBuf, endBuf-startBuf+1); 5750243791Sdim messString += "\n"; 5751243791Sdim 5752243791Sdim // FIXME: Missing definition of 5753243791Sdim // InsertText(clang::SourceLocation, char const*, unsigned int). 5754243791Sdim // InsertText(startLoc, messString.c_str(), messString.size()); 5755243791Sdim // Tried this, but it didn't work either... 5756243791Sdim // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); 5757243791Sdim#endif 5758243791Sdim return RewriteMessageExpr(MessExpr); 5759243791Sdim } 5760243791Sdim 5761243791Sdim if (ObjCAutoreleasePoolStmt *StmtAutoRelease = 5762243791Sdim dyn_cast<ObjCAutoreleasePoolStmt>(S)) { 5763243791Sdim return RewriteObjCAutoreleasePoolStmt(StmtAutoRelease); 5764243791Sdim } 5765243791Sdim 5766243791Sdim if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) 5767243791Sdim return RewriteObjCTryStmt(StmtTry); 5768243791Sdim 5769243791Sdim if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) 5770243791Sdim return RewriteObjCSynchronizedStmt(StmtTry); 5771243791Sdim 5772243791Sdim if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) 5773243791Sdim return RewriteObjCThrowStmt(StmtThrow); 5774243791Sdim 5775243791Sdim if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) 5776243791Sdim return RewriteObjCProtocolExpr(ProtocolExp); 5777243791Sdim 5778243791Sdim if (ObjCForCollectionStmt *StmtForCollection = 5779243791Sdim dyn_cast<ObjCForCollectionStmt>(S)) 5780243791Sdim return RewriteObjCForCollectionStmt(StmtForCollection, 5781243791Sdim OrigStmtRange.getEnd()); 5782243791Sdim if (BreakStmt *StmtBreakStmt = 5783243791Sdim dyn_cast<BreakStmt>(S)) 5784243791Sdim return RewriteBreakStmt(StmtBreakStmt); 5785243791Sdim if (ContinueStmt *StmtContinueStmt = 5786243791Sdim dyn_cast<ContinueStmt>(S)) 5787243791Sdim return RewriteContinueStmt(StmtContinueStmt); 5788243791Sdim 5789243791Sdim // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls 5790243791Sdim // and cast exprs. 5791243791Sdim if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 5792243791Sdim // FIXME: What we're doing here is modifying the type-specifier that 5793243791Sdim // precedes the first Decl. In the future the DeclGroup should have 5794243791Sdim // a separate type-specifier that we can rewrite. 5795243791Sdim // NOTE: We need to avoid rewriting the DeclStmt if it is within 5796243791Sdim // the context of an ObjCForCollectionStmt. For example: 5797243791Sdim // NSArray *someArray; 5798243791Sdim // for (id <FooProtocol> index in someArray) ; 5799243791Sdim // This is because RewriteObjCForCollectionStmt() does textual rewriting 5800243791Sdim // and it depends on the original text locations/positions. 5801243791Sdim if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS)) 5802243791Sdim RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); 5803243791Sdim 5804243791Sdim // Blocks rewrite rules. 5805243791Sdim for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 5806243791Sdim DI != DE; ++DI) { 5807243791Sdim Decl *SD = *DI; 5808243791Sdim if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { 5809243791Sdim if (isTopLevelBlockPointerType(ND->getType())) 5810243791Sdim RewriteBlockPointerDecl(ND); 5811243791Sdim else if (ND->getType()->isFunctionPointerType()) 5812243791Sdim CheckFunctionPointerDecl(ND->getType(), ND); 5813243791Sdim if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { 5814243791Sdim if (VD->hasAttr<BlocksAttr>()) { 5815243791Sdim static unsigned uniqueByrefDeclCount = 0; 5816243791Sdim assert(!BlockByRefDeclNo.count(ND) && 5817243791Sdim "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); 5818243791Sdim BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; 5819243791Sdim RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE)); 5820243791Sdim } 5821243791Sdim else 5822243791Sdim RewriteTypeOfDecl(VD); 5823243791Sdim } 5824243791Sdim } 5825243791Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { 5826243791Sdim if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 5827243791Sdim RewriteBlockPointerDecl(TD); 5828243791Sdim else if (TD->getUnderlyingType()->isFunctionPointerType()) 5829243791Sdim CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 5830243791Sdim } 5831243791Sdim } 5832243791Sdim } 5833243791Sdim 5834243791Sdim if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) 5835243791Sdim RewriteObjCQualifiedInterfaceTypes(CE); 5836243791Sdim 5837243791Sdim if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 5838243791Sdim isa<DoStmt>(S) || isa<ForStmt>(S)) { 5839243791Sdim assert(!Stmts.empty() && "Statement stack is empty"); 5840243791Sdim assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 5841243791Sdim isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 5842243791Sdim && "Statement stack mismatch"); 5843243791Sdim Stmts.pop_back(); 5844243791Sdim } 5845243791Sdim // Handle blocks rewriting. 5846243791Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 5847243791Sdim ValueDecl *VD = DRE->getDecl(); 5848243791Sdim if (VD->hasAttr<BlocksAttr>()) 5849243791Sdim return RewriteBlockDeclRefExpr(DRE); 5850243791Sdim if (HasLocalVariableExternalStorage(VD)) 5851243791Sdim return RewriteLocalVariableExternalStorage(DRE); 5852243791Sdim } 5853243791Sdim 5854243791Sdim if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 5855243791Sdim if (CE->getCallee()->getType()->isBlockPointerType()) { 5856243791Sdim Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); 5857243791Sdim ReplaceStmt(S, BlockCall); 5858243791Sdim return BlockCall; 5859243791Sdim } 5860243791Sdim } 5861243791Sdim if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) { 5862243791Sdim RewriteCastExpr(CE); 5863243791Sdim } 5864243791Sdim if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 5865243791Sdim RewriteImplicitCastObjCExpr(ICE); 5866243791Sdim } 5867243791Sdim#if 0 5868243791Sdim 5869243791Sdim if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 5870243791Sdim CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), 5871243791Sdim ICE->getSubExpr(), 5872243791Sdim SourceLocation()); 5873243791Sdim // Get the new text. 5874243791Sdim std::string SStr; 5875243791Sdim llvm::raw_string_ostream Buf(SStr); 5876243791Sdim Replacement->printPretty(Buf); 5877243791Sdim const std::string &Str = Buf.str(); 5878243791Sdim 5879243791Sdim printf("CAST = %s\n", &Str[0]); 5880243791Sdim InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size()); 5881243791Sdim delete S; 5882243791Sdim return Replacement; 5883243791Sdim } 5884243791Sdim#endif 5885243791Sdim // Return this stmt unmodified. 5886243791Sdim return S; 5887243791Sdim} 5888243791Sdim 5889243791Sdimvoid RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) { 5890243791Sdim for (RecordDecl::field_iterator i = RD->field_begin(), 5891243791Sdim e = RD->field_end(); i != e; ++i) { 5892243791Sdim FieldDecl *FD = *i; 5893243791Sdim if (isTopLevelBlockPointerType(FD->getType())) 5894243791Sdim RewriteBlockPointerDecl(FD); 5895243791Sdim if (FD->getType()->isObjCQualifiedIdType() || 5896243791Sdim FD->getType()->isObjCQualifiedInterfaceType()) 5897243791Sdim RewriteObjCQualifiedInterfaceTypes(FD); 5898243791Sdim } 5899243791Sdim} 5900243791Sdim 5901243791Sdim/// HandleDeclInMainFile - This is called for each top-level decl defined in the 5902243791Sdim/// main file of the input. 5903243791Sdimvoid RewriteModernObjC::HandleDeclInMainFile(Decl *D) { 5904243791Sdim switch (D->getKind()) { 5905243791Sdim case Decl::Function: { 5906243791Sdim FunctionDecl *FD = cast<FunctionDecl>(D); 5907243791Sdim if (FD->isOverloadedOperator()) 5908243791Sdim return; 5909243791Sdim 5910243791Sdim // Since function prototypes don't have ParmDecl's, we check the function 5911243791Sdim // prototype. This enables us to rewrite function declarations and 5912243791Sdim // definitions using the same code. 5913243791Sdim RewriteBlocksInFunctionProtoType(FD->getType(), FD); 5914243791Sdim 5915243791Sdim if (!FD->isThisDeclarationADefinition()) 5916243791Sdim break; 5917243791Sdim 5918243791Sdim // FIXME: If this should support Obj-C++, support CXXTryStmt 5919243791Sdim if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { 5920243791Sdim CurFunctionDef = FD; 5921243791Sdim CurrentBody = Body; 5922243791Sdim Body = 5923243791Sdim cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 5924243791Sdim FD->setBody(Body); 5925243791Sdim CurrentBody = 0; 5926243791Sdim if (PropParentMap) { 5927243791Sdim delete PropParentMap; 5928243791Sdim PropParentMap = 0; 5929243791Sdim } 5930243791Sdim // This synthesizes and inserts the block "impl" struct, invoke function, 5931243791Sdim // and any copy/dispose helper functions. 5932243791Sdim InsertBlockLiteralsWithinFunction(FD); 5933243791Sdim RewriteLineDirective(D); 5934243791Sdim CurFunctionDef = 0; 5935243791Sdim } 5936243791Sdim break; 5937243791Sdim } 5938243791Sdim case Decl::ObjCMethod: { 5939243791Sdim ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); 5940243791Sdim if (CompoundStmt *Body = MD->getCompoundBody()) { 5941243791Sdim CurMethodDef = MD; 5942243791Sdim CurrentBody = Body; 5943243791Sdim Body = 5944243791Sdim cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 5945243791Sdim MD->setBody(Body); 5946243791Sdim CurrentBody = 0; 5947243791Sdim if (PropParentMap) { 5948243791Sdim delete PropParentMap; 5949243791Sdim PropParentMap = 0; 5950243791Sdim } 5951243791Sdim InsertBlockLiteralsWithinMethod(MD); 5952243791Sdim RewriteLineDirective(D); 5953243791Sdim CurMethodDef = 0; 5954243791Sdim } 5955243791Sdim break; 5956243791Sdim } 5957243791Sdim case Decl::ObjCImplementation: { 5958243791Sdim ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D); 5959243791Sdim ClassImplementation.push_back(CI); 5960243791Sdim break; 5961243791Sdim } 5962243791Sdim case Decl::ObjCCategoryImpl: { 5963243791Sdim ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D); 5964243791Sdim CategoryImplementation.push_back(CI); 5965243791Sdim break; 5966243791Sdim } 5967243791Sdim case Decl::Var: { 5968243791Sdim VarDecl *VD = cast<VarDecl>(D); 5969243791Sdim RewriteObjCQualifiedInterfaceTypes(VD); 5970243791Sdim if (isTopLevelBlockPointerType(VD->getType())) 5971243791Sdim RewriteBlockPointerDecl(VD); 5972243791Sdim else if (VD->getType()->isFunctionPointerType()) { 5973243791Sdim CheckFunctionPointerDecl(VD->getType(), VD); 5974243791Sdim if (VD->getInit()) { 5975243791Sdim if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 5976243791Sdim RewriteCastExpr(CE); 5977243791Sdim } 5978243791Sdim } 5979243791Sdim } else if (VD->getType()->isRecordType()) { 5980243791Sdim RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl(); 5981243791Sdim if (RD->isCompleteDefinition()) 5982243791Sdim RewriteRecordBody(RD); 5983243791Sdim } 5984243791Sdim if (VD->getInit()) { 5985243791Sdim GlobalVarDecl = VD; 5986243791Sdim CurrentBody = VD->getInit(); 5987243791Sdim RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); 5988243791Sdim CurrentBody = 0; 5989243791Sdim if (PropParentMap) { 5990243791Sdim delete PropParentMap; 5991243791Sdim PropParentMap = 0; 5992243791Sdim } 5993243791Sdim SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName()); 5994243791Sdim GlobalVarDecl = 0; 5995243791Sdim 5996243791Sdim // This is needed for blocks. 5997243791Sdim if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 5998243791Sdim RewriteCastExpr(CE); 5999243791Sdim } 6000243791Sdim } 6001243791Sdim break; 6002243791Sdim } 6003243791Sdim case Decl::TypeAlias: 6004243791Sdim case Decl::Typedef: { 6005243791Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 6006243791Sdim if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 6007243791Sdim RewriteBlockPointerDecl(TD); 6008243791Sdim else if (TD->getUnderlyingType()->isFunctionPointerType()) 6009243791Sdim CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 6010249423Sdim else 6011249423Sdim RewriteObjCQualifiedInterfaceTypes(TD); 6012243791Sdim } 6013243791Sdim break; 6014243791Sdim } 6015243791Sdim case Decl::CXXRecord: 6016243791Sdim case Decl::Record: { 6017243791Sdim RecordDecl *RD = cast<RecordDecl>(D); 6018243791Sdim if (RD->isCompleteDefinition()) 6019243791Sdim RewriteRecordBody(RD); 6020243791Sdim break; 6021243791Sdim } 6022243791Sdim default: 6023243791Sdim break; 6024243791Sdim } 6025243791Sdim // Nothing yet. 6026243791Sdim} 6027243791Sdim 6028243791Sdim/// Write_ProtocolExprReferencedMetadata - This routine writer out the 6029243791Sdim/// protocol reference symbols in the for of: 6030243791Sdim/// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA. 6031243791Sdimstatic void Write_ProtocolExprReferencedMetadata(ASTContext *Context, 6032243791Sdim ObjCProtocolDecl *PDecl, 6033243791Sdim std::string &Result) { 6034243791Sdim // Also output .objc_protorefs$B section and its meta-data. 6035243791Sdim if (Context->getLangOpts().MicrosoftExt) 6036243791Sdim Result += "static "; 6037243791Sdim Result += "struct _protocol_t *"; 6038243791Sdim Result += "_OBJC_PROTOCOL_REFERENCE_$_"; 6039243791Sdim Result += PDecl->getNameAsString(); 6040243791Sdim Result += " = &"; 6041243791Sdim Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString(); 6042243791Sdim Result += ";\n"; 6043243791Sdim} 6044243791Sdim 6045243791Sdimvoid RewriteModernObjC::HandleTranslationUnit(ASTContext &C) { 6046243791Sdim if (Diags.hasErrorOccurred()) 6047243791Sdim return; 6048243791Sdim 6049243791Sdim RewriteInclude(); 6050243791Sdim 6051249423Sdim for (unsigned i = 0, e = FunctionDefinitionsSeen.size(); i < e; i++) { 6052249423Sdim // translation of function bodies were postponed untill all class and 6053249423Sdim // their extensions and implementations are seen. This is because, we 6054249423Sdim // cannot build grouping structs for bitfields untill they are all seen. 6055249423Sdim FunctionDecl *FDecl = FunctionDefinitionsSeen[i]; 6056249423Sdim HandleTopLevelSingleDecl(FDecl); 6057249423Sdim } 6058249423Sdim 6059243791Sdim // Here's a great place to add any extra declarations that may be needed. 6060243791Sdim // Write out meta data for each @protocol(<expr>). 6061243791Sdim for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 6062243791Sdim E = ProtocolExprDecls.end(); I != E; ++I) { 6063243791Sdim RewriteObjCProtocolMetaData(*I, Preamble); 6064243791Sdim Write_ProtocolExprReferencedMetadata(Context, (*I), Preamble); 6065243791Sdim } 6066243791Sdim 6067243791Sdim InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); 6068243791Sdim 6069243791Sdim if (ClassImplementation.size() || CategoryImplementation.size()) 6070243791Sdim RewriteImplementations(); 6071243791Sdim 6072243791Sdim for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) { 6073243791Sdim ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i]; 6074243791Sdim // Write struct declaration for the class matching its ivar declarations. 6075243791Sdim // Note that for modern abi, this is postponed until the end of TU 6076243791Sdim // because class extensions and the implementation might declare their own 6077243791Sdim // private ivars. 6078243791Sdim RewriteInterfaceDecl(CDecl); 6079243791Sdim } 6080249423Sdim 6081243791Sdim // Get the buffer corresponding to MainFileID. If we haven't changed it, then 6082243791Sdim // we are done. 6083243791Sdim if (const RewriteBuffer *RewriteBuf = 6084243791Sdim Rewrite.getRewriteBufferFor(MainFileID)) { 6085243791Sdim //printf("Changed:\n"); 6086243791Sdim *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 6087243791Sdim } else { 6088243791Sdim llvm::errs() << "No changes\n"; 6089243791Sdim } 6090243791Sdim 6091243791Sdim if (ClassImplementation.size() || CategoryImplementation.size() || 6092243791Sdim ProtocolExprDecls.size()) { 6093243791Sdim // Rewrite Objective-c meta data* 6094243791Sdim std::string ResultStr; 6095243791Sdim RewriteMetaDataIntoBuffer(ResultStr); 6096243791Sdim // Emit metadata. 6097243791Sdim *OutFile << ResultStr; 6098243791Sdim } 6099243791Sdim // Emit ImageInfo; 6100243791Sdim { 6101243791Sdim std::string ResultStr; 6102243791Sdim WriteImageInfo(ResultStr); 6103243791Sdim *OutFile << ResultStr; 6104243791Sdim } 6105243791Sdim OutFile->flush(); 6106243791Sdim} 6107243791Sdim 6108243791Sdimvoid RewriteModernObjC::Initialize(ASTContext &context) { 6109243791Sdim InitializeCommon(context); 6110243791Sdim 6111243791Sdim Preamble += "#ifndef __OBJC2__\n"; 6112243791Sdim Preamble += "#define __OBJC2__\n"; 6113243791Sdim Preamble += "#endif\n"; 6114243791Sdim 6115243791Sdim // declaring objc_selector outside the parameter list removes a silly 6116243791Sdim // scope related warning... 6117243791Sdim if (IsHeader) 6118243791Sdim Preamble = "#pragma once\n"; 6119243791Sdim Preamble += "struct objc_selector; struct objc_class;\n"; 6120243791Sdim Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; "; 6121243791Sdim Preamble += "\n\tstruct objc_object *superClass; "; 6122243791Sdim // Add a constructor for creating temporary objects. 6123243791Sdim Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) "; 6124243791Sdim Preamble += ": object(o), superClass(s) {} "; 6125243791Sdim Preamble += "\n};\n"; 6126243791Sdim 6127243791Sdim if (LangOpts.MicrosoftExt) { 6128243791Sdim // Define all sections using syntax that makes sense. 6129243791Sdim // These are currently generated. 6130243791Sdim Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n"; 6131243791Sdim Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n"; 6132243791Sdim Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n"; 6133243791Sdim Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n"; 6134243791Sdim Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n"; 6135243791Sdim // These are generated but not necessary for functionality. 6136243791Sdim Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n"; 6137243791Sdim Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n"; 6138243791Sdim Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n"; 6139243791Sdim Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n"; 6140243791Sdim 6141243791Sdim // These need be generated for performance. Currently they are not, 6142243791Sdim // using API calls instead. 6143243791Sdim Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n"; 6144243791Sdim Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n"; 6145243791Sdim Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n"; 6146243791Sdim 6147243791Sdim } 6148243791Sdim Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; 6149243791Sdim Preamble += "typedef struct objc_object Protocol;\n"; 6150243791Sdim Preamble += "#define _REWRITER_typedef_Protocol\n"; 6151243791Sdim Preamble += "#endif\n"; 6152243791Sdim if (LangOpts.MicrosoftExt) { 6153243791Sdim Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; 6154243791Sdim Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; 6155243791Sdim } 6156243791Sdim else 6157243791Sdim Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; 6158243791Sdim 6159243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n"; 6160243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n"; 6161243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n"; 6162243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n"; 6163243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n"; 6164243791Sdim 6165243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass"; 6166243791Sdim Preamble += "(const char *);\n"; 6167243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; 6168243791Sdim Preamble += "(struct objc_class *);\n"; 6169243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass"; 6170243791Sdim Preamble += "(const char *);\n"; 6171243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n"; 6172243791Sdim // @synchronized hooks. 6173243791Sdim Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter( struct objc_object *);\n"; 6174243791Sdim Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit( struct objc_object *);\n"; 6175243791Sdim Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; 6176263508Sdim Preamble += "#ifdef _WIN64\n"; 6177263508Sdim Preamble += "typedef unsigned long long _WIN_NSUInteger;\n"; 6178263508Sdim Preamble += "#else\n"; 6179263508Sdim Preamble += "typedef unsigned int _WIN_NSUInteger;\n"; 6180263508Sdim Preamble += "#endif\n"; 6181243791Sdim Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; 6182243791Sdim Preamble += "struct __objcFastEnumerationState {\n\t"; 6183243791Sdim Preamble += "unsigned long state;\n\t"; 6184243791Sdim Preamble += "void **itemsPtr;\n\t"; 6185243791Sdim Preamble += "unsigned long *mutationsPtr;\n\t"; 6186243791Sdim Preamble += "unsigned long extra[5];\n};\n"; 6187243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; 6188243791Sdim Preamble += "#define __FASTENUMERATIONSTATE\n"; 6189243791Sdim Preamble += "#endif\n"; 6190243791Sdim Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; 6191243791Sdim Preamble += "struct __NSConstantStringImpl {\n"; 6192243791Sdim Preamble += " int *isa;\n"; 6193243791Sdim Preamble += " int flags;\n"; 6194243791Sdim Preamble += " char *str;\n"; 6195243791Sdim Preamble += " long length;\n"; 6196243791Sdim Preamble += "};\n"; 6197243791Sdim Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; 6198243791Sdim Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; 6199243791Sdim Preamble += "#else\n"; 6200243791Sdim Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; 6201243791Sdim Preamble += "#endif\n"; 6202243791Sdim Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; 6203243791Sdim Preamble += "#endif\n"; 6204243791Sdim // Blocks preamble. 6205243791Sdim Preamble += "#ifndef BLOCK_IMPL\n"; 6206243791Sdim Preamble += "#define BLOCK_IMPL\n"; 6207243791Sdim Preamble += "struct __block_impl {\n"; 6208243791Sdim Preamble += " void *isa;\n"; 6209243791Sdim Preamble += " int Flags;\n"; 6210243791Sdim Preamble += " int Reserved;\n"; 6211243791Sdim Preamble += " void *FuncPtr;\n"; 6212243791Sdim Preamble += "};\n"; 6213243791Sdim Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; 6214243791Sdim Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; 6215243791Sdim Preamble += "extern \"C\" __declspec(dllexport) " 6216243791Sdim "void _Block_object_assign(void *, const void *, const int);\n"; 6217243791Sdim Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; 6218243791Sdim Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; 6219243791Sdim Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; 6220243791Sdim Preamble += "#else\n"; 6221243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; 6222243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; 6223243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; 6224243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; 6225243791Sdim Preamble += "#endif\n"; 6226243791Sdim Preamble += "#endif\n"; 6227243791Sdim if (LangOpts.MicrosoftExt) { 6228243791Sdim Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; 6229243791Sdim Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; 6230243791Sdim Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. 6231243791Sdim Preamble += "#define __attribute__(X)\n"; 6232243791Sdim Preamble += "#endif\n"; 6233243791Sdim Preamble += "#ifndef __weak\n"; 6234243791Sdim Preamble += "#define __weak\n"; 6235243791Sdim Preamble += "#endif\n"; 6236243791Sdim Preamble += "#ifndef __block\n"; 6237243791Sdim Preamble += "#define __block\n"; 6238243791Sdim Preamble += "#endif\n"; 6239243791Sdim } 6240243791Sdim else { 6241243791Sdim Preamble += "#define __block\n"; 6242243791Sdim Preamble += "#define __weak\n"; 6243243791Sdim } 6244243791Sdim 6245243791Sdim // Declarations required for modern objective-c array and dictionary literals. 6246243791Sdim Preamble += "\n#include <stdarg.h>\n"; 6247243791Sdim Preamble += "struct __NSContainer_literal {\n"; 6248243791Sdim Preamble += " void * *arr;\n"; 6249243791Sdim Preamble += " __NSContainer_literal (unsigned int count, ...) {\n"; 6250243791Sdim Preamble += "\tva_list marker;\n"; 6251243791Sdim Preamble += "\tva_start(marker, count);\n"; 6252243791Sdim Preamble += "\tarr = new void *[count];\n"; 6253243791Sdim Preamble += "\tfor (unsigned i = 0; i < count; i++)\n"; 6254243791Sdim Preamble += "\t arr[i] = va_arg(marker, void *);\n"; 6255243791Sdim Preamble += "\tva_end( marker );\n"; 6256243791Sdim Preamble += " };\n"; 6257243791Sdim Preamble += " ~__NSContainer_literal() {\n"; 6258243791Sdim Preamble += "\tdelete[] arr;\n"; 6259243791Sdim Preamble += " }\n"; 6260243791Sdim Preamble += "};\n"; 6261243791Sdim 6262243791Sdim // Declaration required for implementation of @autoreleasepool statement. 6263243791Sdim Preamble += "extern \"C\" __declspec(dllimport) void * objc_autoreleasePoolPush(void);\n"; 6264243791Sdim Preamble += "extern \"C\" __declspec(dllimport) void objc_autoreleasePoolPop(void *);\n\n"; 6265243791Sdim Preamble += "struct __AtAutoreleasePool {\n"; 6266243791Sdim Preamble += " __AtAutoreleasePool() {atautoreleasepoolobj = objc_autoreleasePoolPush();}\n"; 6267243791Sdim Preamble += " ~__AtAutoreleasePool() {objc_autoreleasePoolPop(atautoreleasepoolobj);}\n"; 6268243791Sdim Preamble += " void * atautoreleasepoolobj;\n"; 6269243791Sdim Preamble += "};\n"; 6270243791Sdim 6271243791Sdim // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long 6272243791Sdim // as this avoids warning in any 64bit/32bit compilation model. 6273243791Sdim Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; 6274243791Sdim} 6275243791Sdim 6276243791Sdim/// RewriteIvarOffsetComputation - This rutine synthesizes computation of 6277243791Sdim/// ivar offset. 6278243791Sdimvoid RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 6279243791Sdim std::string &Result) { 6280249423Sdim Result += "__OFFSETOFIVAR__(struct "; 6281249423Sdim Result += ivar->getContainingInterface()->getNameAsString(); 6282249423Sdim if (LangOpts.MicrosoftExt) 6283249423Sdim Result += "_IMPL"; 6284249423Sdim Result += ", "; 6285249423Sdim if (ivar->isBitField()) 6286249423Sdim ObjCIvarBitfieldGroupDecl(ivar, Result); 6287249423Sdim else 6288243791Sdim Result += ivar->getNameAsString(); 6289249423Sdim Result += ")"; 6290243791Sdim} 6291243791Sdim 6292243791Sdim/// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI. 6293243791Sdim/// struct _prop_t { 6294243791Sdim/// const char *name; 6295243791Sdim/// char *attributes; 6296243791Sdim/// } 6297243791Sdim 6298243791Sdim/// struct _prop_list_t { 6299243791Sdim/// uint32_t entsize; // sizeof(struct _prop_t) 6300243791Sdim/// uint32_t count_of_properties; 6301243791Sdim/// struct _prop_t prop_list[count_of_properties]; 6302243791Sdim/// } 6303243791Sdim 6304243791Sdim/// struct _protocol_t; 6305243791Sdim 6306243791Sdim/// struct _protocol_list_t { 6307243791Sdim/// long protocol_count; // Note, this is 32/64 bit 6308243791Sdim/// struct _protocol_t * protocol_list[protocol_count]; 6309243791Sdim/// } 6310243791Sdim 6311243791Sdim/// struct _objc_method { 6312243791Sdim/// SEL _cmd; 6313243791Sdim/// const char *method_type; 6314243791Sdim/// char *_imp; 6315243791Sdim/// } 6316243791Sdim 6317243791Sdim/// struct _method_list_t { 6318243791Sdim/// uint32_t entsize; // sizeof(struct _objc_method) 6319243791Sdim/// uint32_t method_count; 6320243791Sdim/// struct _objc_method method_list[method_count]; 6321243791Sdim/// } 6322243791Sdim 6323243791Sdim/// struct _protocol_t { 6324243791Sdim/// id isa; // NULL 6325243791Sdim/// const char *protocol_name; 6326243791Sdim/// const struct _protocol_list_t * protocol_list; // super protocols 6327243791Sdim/// const struct method_list_t *instance_methods; 6328243791Sdim/// const struct method_list_t *class_methods; 6329243791Sdim/// const struct method_list_t *optionalInstanceMethods; 6330243791Sdim/// const struct method_list_t *optionalClassMethods; 6331243791Sdim/// const struct _prop_list_t * properties; 6332243791Sdim/// const uint32_t size; // sizeof(struct _protocol_t) 6333243791Sdim/// const uint32_t flags; // = 0 6334243791Sdim/// const char ** extendedMethodTypes; 6335243791Sdim/// } 6336243791Sdim 6337243791Sdim/// struct _ivar_t { 6338243791Sdim/// unsigned long int *offset; // pointer to ivar offset location 6339243791Sdim/// const char *name; 6340243791Sdim/// const char *type; 6341243791Sdim/// uint32_t alignment; 6342243791Sdim/// uint32_t size; 6343243791Sdim/// } 6344243791Sdim 6345243791Sdim/// struct _ivar_list_t { 6346243791Sdim/// uint32 entsize; // sizeof(struct _ivar_t) 6347243791Sdim/// uint32 count; 6348243791Sdim/// struct _ivar_t list[count]; 6349243791Sdim/// } 6350243791Sdim 6351243791Sdim/// struct _class_ro_t { 6352243791Sdim/// uint32_t flags; 6353243791Sdim/// uint32_t instanceStart; 6354243791Sdim/// uint32_t instanceSize; 6355243791Sdim/// uint32_t reserved; // only when building for 64bit targets 6356243791Sdim/// const uint8_t *ivarLayout; 6357243791Sdim/// const char *name; 6358243791Sdim/// const struct _method_list_t *baseMethods; 6359243791Sdim/// const struct _protocol_list_t *baseProtocols; 6360243791Sdim/// const struct _ivar_list_t *ivars; 6361243791Sdim/// const uint8_t *weakIvarLayout; 6362243791Sdim/// const struct _prop_list_t *properties; 6363243791Sdim/// } 6364243791Sdim 6365243791Sdim/// struct _class_t { 6366243791Sdim/// struct _class_t *isa; 6367243791Sdim/// struct _class_t *superclass; 6368243791Sdim/// void *cache; 6369243791Sdim/// IMP *vtable; 6370243791Sdim/// struct _class_ro_t *ro; 6371243791Sdim/// } 6372243791Sdim 6373243791Sdim/// struct _category_t { 6374243791Sdim/// const char *name; 6375243791Sdim/// struct _class_t *cls; 6376243791Sdim/// const struct _method_list_t *instance_methods; 6377243791Sdim/// const struct _method_list_t *class_methods; 6378243791Sdim/// const struct _protocol_list_t *protocols; 6379243791Sdim/// const struct _prop_list_t *properties; 6380243791Sdim/// } 6381243791Sdim 6382243791Sdim/// MessageRefTy - LLVM for: 6383243791Sdim/// struct _message_ref_t { 6384243791Sdim/// IMP messenger; 6385243791Sdim/// SEL name; 6386243791Sdim/// }; 6387243791Sdim 6388243791Sdim/// SuperMessageRefTy - LLVM for: 6389243791Sdim/// struct _super_message_ref_t { 6390243791Sdim/// SUPER_IMP messenger; 6391243791Sdim/// SEL name; 6392243791Sdim/// }; 6393243791Sdim 6394243791Sdimstatic void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) { 6395243791Sdim static bool meta_data_declared = false; 6396243791Sdim if (meta_data_declared) 6397243791Sdim return; 6398243791Sdim 6399243791Sdim Result += "\nstruct _prop_t {\n"; 6400243791Sdim Result += "\tconst char *name;\n"; 6401243791Sdim Result += "\tconst char *attributes;\n"; 6402243791Sdim Result += "};\n"; 6403243791Sdim 6404243791Sdim Result += "\nstruct _protocol_t;\n"; 6405243791Sdim 6406243791Sdim Result += "\nstruct _objc_method {\n"; 6407243791Sdim Result += "\tstruct objc_selector * _cmd;\n"; 6408243791Sdim Result += "\tconst char *method_type;\n"; 6409243791Sdim Result += "\tvoid *_imp;\n"; 6410243791Sdim Result += "};\n"; 6411243791Sdim 6412243791Sdim Result += "\nstruct _protocol_t {\n"; 6413243791Sdim Result += "\tvoid * isa; // NULL\n"; 6414243791Sdim Result += "\tconst char *protocol_name;\n"; 6415243791Sdim Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n"; 6416243791Sdim Result += "\tconst struct method_list_t *instance_methods;\n"; 6417243791Sdim Result += "\tconst struct method_list_t *class_methods;\n"; 6418243791Sdim Result += "\tconst struct method_list_t *optionalInstanceMethods;\n"; 6419243791Sdim Result += "\tconst struct method_list_t *optionalClassMethods;\n"; 6420243791Sdim Result += "\tconst struct _prop_list_t * properties;\n"; 6421243791Sdim Result += "\tconst unsigned int size; // sizeof(struct _protocol_t)\n"; 6422243791Sdim Result += "\tconst unsigned int flags; // = 0\n"; 6423243791Sdim Result += "\tconst char ** extendedMethodTypes;\n"; 6424243791Sdim Result += "};\n"; 6425243791Sdim 6426243791Sdim Result += "\nstruct _ivar_t {\n"; 6427243791Sdim Result += "\tunsigned long int *offset; // pointer to ivar offset location\n"; 6428243791Sdim Result += "\tconst char *name;\n"; 6429243791Sdim Result += "\tconst char *type;\n"; 6430243791Sdim Result += "\tunsigned int alignment;\n"; 6431243791Sdim Result += "\tunsigned int size;\n"; 6432243791Sdim Result += "};\n"; 6433243791Sdim 6434243791Sdim Result += "\nstruct _class_ro_t {\n"; 6435243791Sdim Result += "\tunsigned int flags;\n"; 6436243791Sdim Result += "\tunsigned int instanceStart;\n"; 6437243791Sdim Result += "\tunsigned int instanceSize;\n"; 6438243791Sdim const llvm::Triple &Triple(Context->getTargetInfo().getTriple()); 6439243791Sdim if (Triple.getArch() == llvm::Triple::x86_64) 6440243791Sdim Result += "\tunsigned int reserved;\n"; 6441243791Sdim Result += "\tconst unsigned char *ivarLayout;\n"; 6442243791Sdim Result += "\tconst char *name;\n"; 6443243791Sdim Result += "\tconst struct _method_list_t *baseMethods;\n"; 6444243791Sdim Result += "\tconst struct _objc_protocol_list *baseProtocols;\n"; 6445243791Sdim Result += "\tconst struct _ivar_list_t *ivars;\n"; 6446243791Sdim Result += "\tconst unsigned char *weakIvarLayout;\n"; 6447243791Sdim Result += "\tconst struct _prop_list_t *properties;\n"; 6448243791Sdim Result += "};\n"; 6449243791Sdim 6450243791Sdim Result += "\nstruct _class_t {\n"; 6451243791Sdim Result += "\tstruct _class_t *isa;\n"; 6452243791Sdim Result += "\tstruct _class_t *superclass;\n"; 6453243791Sdim Result += "\tvoid *cache;\n"; 6454243791Sdim Result += "\tvoid *vtable;\n"; 6455243791Sdim Result += "\tstruct _class_ro_t *ro;\n"; 6456243791Sdim Result += "};\n"; 6457243791Sdim 6458243791Sdim Result += "\nstruct _category_t {\n"; 6459243791Sdim Result += "\tconst char *name;\n"; 6460243791Sdim Result += "\tstruct _class_t *cls;\n"; 6461243791Sdim Result += "\tconst struct _method_list_t *instance_methods;\n"; 6462243791Sdim Result += "\tconst struct _method_list_t *class_methods;\n"; 6463243791Sdim Result += "\tconst struct _protocol_list_t *protocols;\n"; 6464243791Sdim Result += "\tconst struct _prop_list_t *properties;\n"; 6465243791Sdim Result += "};\n"; 6466243791Sdim 6467243791Sdim Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n"; 6468243791Sdim Result += "#pragma warning(disable:4273)\n"; 6469243791Sdim meta_data_declared = true; 6470243791Sdim} 6471243791Sdim 6472243791Sdimstatic void Write_protocol_list_t_TypeDecl(std::string &Result, 6473243791Sdim long super_protocol_count) { 6474243791Sdim Result += "struct /*_protocol_list_t*/"; Result += " {\n"; 6475243791Sdim Result += "\tlong protocol_count; // Note, this is 32/64 bit\n"; 6476243791Sdim Result += "\tstruct _protocol_t *super_protocols["; 6477243791Sdim Result += utostr(super_protocol_count); Result += "];\n"; 6478243791Sdim Result += "}"; 6479243791Sdim} 6480243791Sdim 6481243791Sdimstatic void Write_method_list_t_TypeDecl(std::string &Result, 6482243791Sdim unsigned int method_count) { 6483243791Sdim Result += "struct /*_method_list_t*/"; Result += " {\n"; 6484243791Sdim Result += "\tunsigned int entsize; // sizeof(struct _objc_method)\n"; 6485243791Sdim Result += "\tunsigned int method_count;\n"; 6486243791Sdim Result += "\tstruct _objc_method method_list["; 6487243791Sdim Result += utostr(method_count); Result += "];\n"; 6488243791Sdim Result += "}"; 6489243791Sdim} 6490243791Sdim 6491243791Sdimstatic void Write__prop_list_t_TypeDecl(std::string &Result, 6492243791Sdim unsigned int property_count) { 6493243791Sdim Result += "struct /*_prop_list_t*/"; Result += " {\n"; 6494243791Sdim Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n"; 6495243791Sdim Result += "\tunsigned int count_of_properties;\n"; 6496243791Sdim Result += "\tstruct _prop_t prop_list["; 6497243791Sdim Result += utostr(property_count); Result += "];\n"; 6498243791Sdim Result += "}"; 6499243791Sdim} 6500243791Sdim 6501243791Sdimstatic void Write__ivar_list_t_TypeDecl(std::string &Result, 6502243791Sdim unsigned int ivar_count) { 6503243791Sdim Result += "struct /*_ivar_list_t*/"; Result += " {\n"; 6504243791Sdim Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n"; 6505243791Sdim Result += "\tunsigned int count;\n"; 6506243791Sdim Result += "\tstruct _ivar_t ivar_list["; 6507243791Sdim Result += utostr(ivar_count); Result += "];\n"; 6508243791Sdim Result += "}"; 6509243791Sdim} 6510243791Sdim 6511243791Sdimstatic void Write_protocol_list_initializer(ASTContext *Context, std::string &Result, 6512243791Sdim ArrayRef<ObjCProtocolDecl *> SuperProtocols, 6513243791Sdim StringRef VarName, 6514243791Sdim StringRef ProtocolName) { 6515243791Sdim if (SuperProtocols.size() > 0) { 6516243791Sdim Result += "\nstatic "; 6517243791Sdim Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size()); 6518243791Sdim Result += " "; Result += VarName; 6519243791Sdim Result += ProtocolName; 6520243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 6521243791Sdim Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n"; 6522243791Sdim for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) { 6523243791Sdim ObjCProtocolDecl *SuperPD = SuperProtocols[i]; 6524243791Sdim Result += "\t&"; Result += "_OBJC_PROTOCOL_"; 6525243791Sdim Result += SuperPD->getNameAsString(); 6526243791Sdim if (i == e-1) 6527243791Sdim Result += "\n};\n"; 6528243791Sdim else 6529243791Sdim Result += ",\n"; 6530243791Sdim } 6531243791Sdim } 6532243791Sdim} 6533243791Sdim 6534243791Sdimstatic void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj, 6535243791Sdim ASTContext *Context, std::string &Result, 6536243791Sdim ArrayRef<ObjCMethodDecl *> Methods, 6537243791Sdim StringRef VarName, 6538243791Sdim StringRef TopLevelDeclName, 6539243791Sdim bool MethodImpl) { 6540243791Sdim if (Methods.size() > 0) { 6541243791Sdim Result += "\nstatic "; 6542243791Sdim Write_method_list_t_TypeDecl(Result, Methods.size()); 6543243791Sdim Result += " "; Result += VarName; 6544243791Sdim Result += TopLevelDeclName; 6545243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 6546243791Sdim Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n"; 6547243791Sdim Result += "\t"; Result += utostr(Methods.size()); Result += ",\n"; 6548243791Sdim for (unsigned i = 0, e = Methods.size(); i < e; i++) { 6549243791Sdim ObjCMethodDecl *MD = Methods[i]; 6550243791Sdim if (i == 0) 6551243791Sdim Result += "\t{{(struct objc_selector *)\""; 6552243791Sdim else 6553243791Sdim Result += "\t{(struct objc_selector *)\""; 6554243791Sdim Result += (MD)->getSelector().getAsString(); Result += "\""; 6555243791Sdim Result += ", "; 6556243791Sdim std::string MethodTypeString; 6557243791Sdim Context->getObjCEncodingForMethodDecl(MD, MethodTypeString); 6558243791Sdim Result += "\""; Result += MethodTypeString; Result += "\""; 6559243791Sdim Result += ", "; 6560243791Sdim if (!MethodImpl) 6561243791Sdim Result += "0"; 6562243791Sdim else { 6563243791Sdim Result += "(void *)"; 6564243791Sdim Result += RewriteObj.MethodInternalNames[MD]; 6565243791Sdim } 6566243791Sdim if (i == e-1) 6567243791Sdim Result += "}}\n"; 6568243791Sdim else 6569243791Sdim Result += "},\n"; 6570243791Sdim } 6571243791Sdim Result += "};\n"; 6572243791Sdim } 6573243791Sdim} 6574243791Sdim 6575243791Sdimstatic void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj, 6576243791Sdim ASTContext *Context, std::string &Result, 6577243791Sdim ArrayRef<ObjCPropertyDecl *> Properties, 6578243791Sdim const Decl *Container, 6579243791Sdim StringRef VarName, 6580243791Sdim StringRef ProtocolName) { 6581243791Sdim if (Properties.size() > 0) { 6582243791Sdim Result += "\nstatic "; 6583243791Sdim Write__prop_list_t_TypeDecl(Result, Properties.size()); 6584243791Sdim Result += " "; Result += VarName; 6585243791Sdim Result += ProtocolName; 6586243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 6587243791Sdim Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n"; 6588243791Sdim Result += "\t"; Result += utostr(Properties.size()); Result += ",\n"; 6589243791Sdim for (unsigned i = 0, e = Properties.size(); i < e; i++) { 6590243791Sdim ObjCPropertyDecl *PropDecl = Properties[i]; 6591243791Sdim if (i == 0) 6592243791Sdim Result += "\t{{\""; 6593243791Sdim else 6594243791Sdim Result += "\t{\""; 6595243791Sdim Result += PropDecl->getName(); Result += "\","; 6596243791Sdim std::string PropertyTypeString, QuotePropertyTypeString; 6597243791Sdim Context->getObjCEncodingForPropertyDecl(PropDecl, Container, PropertyTypeString); 6598243791Sdim RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString); 6599243791Sdim Result += "\""; Result += QuotePropertyTypeString; Result += "\""; 6600243791Sdim if (i == e-1) 6601243791Sdim Result += "}}\n"; 6602243791Sdim else 6603243791Sdim Result += "},\n"; 6604243791Sdim } 6605243791Sdim Result += "};\n"; 6606243791Sdim } 6607243791Sdim} 6608243791Sdim 6609243791Sdim// Metadata flags 6610243791Sdimenum MetaDataDlags { 6611243791Sdim CLS = 0x0, 6612243791Sdim CLS_META = 0x1, 6613243791Sdim CLS_ROOT = 0x2, 6614243791Sdim OBJC2_CLS_HIDDEN = 0x10, 6615243791Sdim CLS_EXCEPTION = 0x20, 6616243791Sdim 6617243791Sdim /// (Obsolete) ARC-specific: this class has a .release_ivars method 6618243791Sdim CLS_HAS_IVAR_RELEASER = 0x40, 6619243791Sdim /// class was compiled with -fobjc-arr 6620243791Sdim CLS_COMPILED_BY_ARC = 0x80 // (1<<7) 6621243791Sdim}; 6622243791Sdim 6623243791Sdimstatic void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result, 6624243791Sdim unsigned int flags, 6625243791Sdim const std::string &InstanceStart, 6626243791Sdim const std::string &InstanceSize, 6627243791Sdim ArrayRef<ObjCMethodDecl *>baseMethods, 6628243791Sdim ArrayRef<ObjCProtocolDecl *>baseProtocols, 6629243791Sdim ArrayRef<ObjCIvarDecl *>ivars, 6630243791Sdim ArrayRef<ObjCPropertyDecl *>Properties, 6631243791Sdim StringRef VarName, 6632243791Sdim StringRef ClassName) { 6633243791Sdim Result += "\nstatic struct _class_ro_t "; 6634243791Sdim Result += VarName; Result += ClassName; 6635243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 6636243791Sdim Result += "\t"; 6637243791Sdim Result += llvm::utostr(flags); Result += ", "; 6638243791Sdim Result += InstanceStart; Result += ", "; 6639243791Sdim Result += InstanceSize; Result += ", \n"; 6640243791Sdim Result += "\t"; 6641243791Sdim const llvm::Triple &Triple(Context->getTargetInfo().getTriple()); 6642243791Sdim if (Triple.getArch() == llvm::Triple::x86_64) 6643243791Sdim // uint32_t const reserved; // only when building for 64bit targets 6644243791Sdim Result += "(unsigned int)0, \n\t"; 6645243791Sdim // const uint8_t * const ivarLayout; 6646243791Sdim Result += "0, \n\t"; 6647243791Sdim Result += "\""; Result += ClassName; Result += "\",\n\t"; 6648243791Sdim bool metaclass = ((flags & CLS_META) != 0); 6649243791Sdim if (baseMethods.size() > 0) { 6650243791Sdim Result += "(const struct _method_list_t *)&"; 6651243791Sdim if (metaclass) 6652243791Sdim Result += "_OBJC_$_CLASS_METHODS_"; 6653243791Sdim else 6654243791Sdim Result += "_OBJC_$_INSTANCE_METHODS_"; 6655243791Sdim Result += ClassName; 6656243791Sdim Result += ",\n\t"; 6657243791Sdim } 6658243791Sdim else 6659243791Sdim Result += "0, \n\t"; 6660243791Sdim 6661243791Sdim if (!metaclass && baseProtocols.size() > 0) { 6662243791Sdim Result += "(const struct _objc_protocol_list *)&"; 6663243791Sdim Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName; 6664243791Sdim Result += ",\n\t"; 6665243791Sdim } 6666243791Sdim else 6667243791Sdim Result += "0, \n\t"; 6668243791Sdim 6669243791Sdim if (!metaclass && ivars.size() > 0) { 6670243791Sdim Result += "(const struct _ivar_list_t *)&"; 6671243791Sdim Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName; 6672243791Sdim Result += ",\n\t"; 6673243791Sdim } 6674243791Sdim else 6675243791Sdim Result += "0, \n\t"; 6676243791Sdim 6677243791Sdim // weakIvarLayout 6678243791Sdim Result += "0, \n\t"; 6679243791Sdim if (!metaclass && Properties.size() > 0) { 6680243791Sdim Result += "(const struct _prop_list_t *)&"; 6681243791Sdim Result += "_OBJC_$_PROP_LIST_"; Result += ClassName; 6682243791Sdim Result += ",\n"; 6683243791Sdim } 6684243791Sdim else 6685243791Sdim Result += "0, \n"; 6686243791Sdim 6687243791Sdim Result += "};\n"; 6688243791Sdim} 6689243791Sdim 6690243791Sdimstatic void Write_class_t(ASTContext *Context, std::string &Result, 6691243791Sdim StringRef VarName, 6692243791Sdim const ObjCInterfaceDecl *CDecl, bool metaclass) { 6693243791Sdim bool rootClass = (!CDecl->getSuperClass()); 6694243791Sdim const ObjCInterfaceDecl *RootClass = CDecl; 6695243791Sdim 6696243791Sdim if (!rootClass) { 6697243791Sdim // Find the Root class 6698243791Sdim RootClass = CDecl->getSuperClass(); 6699243791Sdim while (RootClass->getSuperClass()) { 6700243791Sdim RootClass = RootClass->getSuperClass(); 6701243791Sdim } 6702243791Sdim } 6703243791Sdim 6704243791Sdim if (metaclass && rootClass) { 6705243791Sdim // Need to handle a case of use of forward declaration. 6706243791Sdim Result += "\n"; 6707243791Sdim Result += "extern \"C\" "; 6708243791Sdim if (CDecl->getImplementation()) 6709243791Sdim Result += "__declspec(dllexport) "; 6710243791Sdim else 6711243791Sdim Result += "__declspec(dllimport) "; 6712243791Sdim 6713243791Sdim Result += "struct _class_t OBJC_CLASS_$_"; 6714243791Sdim Result += CDecl->getNameAsString(); 6715243791Sdim Result += ";\n"; 6716243791Sdim } 6717243791Sdim // Also, for possibility of 'super' metadata class not having been defined yet. 6718243791Sdim if (!rootClass) { 6719243791Sdim ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); 6720243791Sdim Result += "\n"; 6721243791Sdim Result += "extern \"C\" "; 6722243791Sdim if (SuperClass->getImplementation()) 6723243791Sdim Result += "__declspec(dllexport) "; 6724243791Sdim else 6725243791Sdim Result += "__declspec(dllimport) "; 6726243791Sdim 6727243791Sdim Result += "struct _class_t "; 6728243791Sdim Result += VarName; 6729243791Sdim Result += SuperClass->getNameAsString(); 6730243791Sdim Result += ";\n"; 6731243791Sdim 6732243791Sdim if (metaclass && RootClass != SuperClass) { 6733243791Sdim Result += "extern \"C\" "; 6734243791Sdim if (RootClass->getImplementation()) 6735243791Sdim Result += "__declspec(dllexport) "; 6736243791Sdim else 6737243791Sdim Result += "__declspec(dllimport) "; 6738243791Sdim 6739243791Sdim Result += "struct _class_t "; 6740243791Sdim Result += VarName; 6741243791Sdim Result += RootClass->getNameAsString(); 6742243791Sdim Result += ";\n"; 6743243791Sdim } 6744243791Sdim } 6745243791Sdim 6746243791Sdim Result += "\nextern \"C\" __declspec(dllexport) struct _class_t "; 6747243791Sdim Result += VarName; Result += CDecl->getNameAsString(); 6748243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n"; 6749243791Sdim Result += "\t"; 6750243791Sdim if (metaclass) { 6751243791Sdim if (!rootClass) { 6752243791Sdim Result += "0, // &"; Result += VarName; 6753243791Sdim Result += RootClass->getNameAsString(); 6754243791Sdim Result += ",\n\t"; 6755243791Sdim Result += "0, // &"; Result += VarName; 6756243791Sdim Result += CDecl->getSuperClass()->getNameAsString(); 6757243791Sdim Result += ",\n\t"; 6758243791Sdim } 6759243791Sdim else { 6760243791Sdim Result += "0, // &"; Result += VarName; 6761243791Sdim Result += CDecl->getNameAsString(); 6762243791Sdim Result += ",\n\t"; 6763243791Sdim Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 6764243791Sdim Result += ",\n\t"; 6765243791Sdim } 6766243791Sdim } 6767243791Sdim else { 6768243791Sdim Result += "0, // &OBJC_METACLASS_$_"; 6769243791Sdim Result += CDecl->getNameAsString(); 6770243791Sdim Result += ",\n\t"; 6771243791Sdim if (!rootClass) { 6772243791Sdim Result += "0, // &"; Result += VarName; 6773243791Sdim Result += CDecl->getSuperClass()->getNameAsString(); 6774243791Sdim Result += ",\n\t"; 6775243791Sdim } 6776243791Sdim else 6777243791Sdim Result += "0,\n\t"; 6778243791Sdim } 6779243791Sdim Result += "0, // (void *)&_objc_empty_cache,\n\t"; 6780243791Sdim Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t"; 6781243791Sdim if (metaclass) 6782243791Sdim Result += "&_OBJC_METACLASS_RO_$_"; 6783243791Sdim else 6784243791Sdim Result += "&_OBJC_CLASS_RO_$_"; 6785243791Sdim Result += CDecl->getNameAsString(); 6786243791Sdim Result += ",\n};\n"; 6787243791Sdim 6788243791Sdim // Add static function to initialize some of the meta-data fields. 6789243791Sdim // avoid doing it twice. 6790243791Sdim if (metaclass) 6791243791Sdim return; 6792243791Sdim 6793243791Sdim const ObjCInterfaceDecl *SuperClass = 6794243791Sdim rootClass ? CDecl : CDecl->getSuperClass(); 6795243791Sdim 6796243791Sdim Result += "static void OBJC_CLASS_SETUP_$_"; 6797243791Sdim Result += CDecl->getNameAsString(); 6798243791Sdim Result += "(void ) {\n"; 6799243791Sdim Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 6800243791Sdim Result += ".isa = "; Result += "&OBJC_METACLASS_$_"; 6801243791Sdim Result += RootClass->getNameAsString(); Result += ";\n"; 6802243791Sdim 6803243791Sdim Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 6804243791Sdim Result += ".superclass = "; 6805243791Sdim if (rootClass) 6806243791Sdim Result += "&OBJC_CLASS_$_"; 6807243791Sdim else 6808243791Sdim Result += "&OBJC_METACLASS_$_"; 6809243791Sdim 6810243791Sdim Result += SuperClass->getNameAsString(); Result += ";\n"; 6811243791Sdim 6812243791Sdim Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 6813243791Sdim Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n"; 6814243791Sdim 6815243791Sdim Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 6816243791Sdim Result += ".isa = "; Result += "&OBJC_METACLASS_$_"; 6817243791Sdim Result += CDecl->getNameAsString(); Result += ";\n"; 6818243791Sdim 6819243791Sdim if (!rootClass) { 6820243791Sdim Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 6821243791Sdim Result += ".superclass = "; Result += "&OBJC_CLASS_$_"; 6822243791Sdim Result += SuperClass->getNameAsString(); Result += ";\n"; 6823243791Sdim } 6824243791Sdim 6825243791Sdim Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 6826243791Sdim Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n"; 6827243791Sdim Result += "}\n"; 6828243791Sdim} 6829243791Sdim 6830243791Sdimstatic void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context, 6831243791Sdim std::string &Result, 6832243791Sdim ObjCCategoryDecl *CatDecl, 6833243791Sdim ObjCInterfaceDecl *ClassDecl, 6834243791Sdim ArrayRef<ObjCMethodDecl *> InstanceMethods, 6835243791Sdim ArrayRef<ObjCMethodDecl *> ClassMethods, 6836243791Sdim ArrayRef<ObjCProtocolDecl *> RefedProtocols, 6837243791Sdim ArrayRef<ObjCPropertyDecl *> ClassProperties) { 6838243791Sdim StringRef CatName = CatDecl->getName(); 6839243791Sdim StringRef ClassName = ClassDecl->getName(); 6840243791Sdim // must declare an extern class object in case this class is not implemented 6841243791Sdim // in this TU. 6842243791Sdim Result += "\n"; 6843243791Sdim Result += "extern \"C\" "; 6844243791Sdim if (ClassDecl->getImplementation()) 6845243791Sdim Result += "__declspec(dllexport) "; 6846243791Sdim else 6847243791Sdim Result += "__declspec(dllimport) "; 6848243791Sdim 6849243791Sdim Result += "struct _class_t "; 6850243791Sdim Result += "OBJC_CLASS_$_"; Result += ClassName; 6851243791Sdim Result += ";\n"; 6852243791Sdim 6853243791Sdim Result += "\nstatic struct _category_t "; 6854243791Sdim Result += "_OBJC_$_CATEGORY_"; 6855243791Sdim Result += ClassName; Result += "_$_"; Result += CatName; 6856243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n"; 6857243791Sdim Result += "{\n"; 6858243791Sdim Result += "\t\""; Result += ClassName; Result += "\",\n"; 6859243791Sdim Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName; 6860243791Sdim Result += ",\n"; 6861243791Sdim if (InstanceMethods.size() > 0) { 6862243791Sdim Result += "\t(const struct _method_list_t *)&"; 6863243791Sdim Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_"; 6864243791Sdim Result += ClassName; Result += "_$_"; Result += CatName; 6865243791Sdim Result += ",\n"; 6866243791Sdim } 6867243791Sdim else 6868243791Sdim Result += "\t0,\n"; 6869243791Sdim 6870243791Sdim if (ClassMethods.size() > 0) { 6871243791Sdim Result += "\t(const struct _method_list_t *)&"; 6872243791Sdim Result += "_OBJC_$_CATEGORY_CLASS_METHODS_"; 6873243791Sdim Result += ClassName; Result += "_$_"; Result += CatName; 6874243791Sdim Result += ",\n"; 6875243791Sdim } 6876243791Sdim else 6877243791Sdim Result += "\t0,\n"; 6878243791Sdim 6879243791Sdim if (RefedProtocols.size() > 0) { 6880243791Sdim Result += "\t(const struct _protocol_list_t *)&"; 6881243791Sdim Result += "_OBJC_CATEGORY_PROTOCOLS_$_"; 6882243791Sdim Result += ClassName; Result += "_$_"; Result += CatName; 6883243791Sdim Result += ",\n"; 6884243791Sdim } 6885243791Sdim else 6886243791Sdim Result += "\t0,\n"; 6887243791Sdim 6888243791Sdim if (ClassProperties.size() > 0) { 6889243791Sdim Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_"; 6890243791Sdim Result += ClassName; Result += "_$_"; Result += CatName; 6891243791Sdim Result += ",\n"; 6892243791Sdim } 6893243791Sdim else 6894243791Sdim Result += "\t0,\n"; 6895243791Sdim 6896243791Sdim Result += "};\n"; 6897243791Sdim 6898243791Sdim // Add static function to initialize the class pointer in the category structure. 6899243791Sdim Result += "static void OBJC_CATEGORY_SETUP_$_"; 6900243791Sdim Result += ClassDecl->getNameAsString(); 6901243791Sdim Result += "_$_"; 6902243791Sdim Result += CatName; 6903243791Sdim Result += "(void ) {\n"; 6904243791Sdim Result += "\t_OBJC_$_CATEGORY_"; 6905243791Sdim Result += ClassDecl->getNameAsString(); 6906243791Sdim Result += "_$_"; 6907243791Sdim Result += CatName; 6908243791Sdim Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName; 6909243791Sdim Result += ";\n}\n"; 6910243791Sdim} 6911243791Sdim 6912243791Sdimstatic void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj, 6913243791Sdim ASTContext *Context, std::string &Result, 6914243791Sdim ArrayRef<ObjCMethodDecl *> Methods, 6915243791Sdim StringRef VarName, 6916243791Sdim StringRef ProtocolName) { 6917243791Sdim if (Methods.size() == 0) 6918243791Sdim return; 6919243791Sdim 6920243791Sdim Result += "\nstatic const char *"; 6921243791Sdim Result += VarName; Result += ProtocolName; 6922243791Sdim Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n"; 6923243791Sdim Result += "{\n"; 6924243791Sdim for (unsigned i = 0, e = Methods.size(); i < e; i++) { 6925243791Sdim ObjCMethodDecl *MD = Methods[i]; 6926243791Sdim std::string MethodTypeString, QuoteMethodTypeString; 6927243791Sdim Context->getObjCEncodingForMethodDecl(MD, MethodTypeString, true); 6928243791Sdim RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString); 6929243791Sdim Result += "\t\""; Result += QuoteMethodTypeString; Result += "\""; 6930243791Sdim if (i == e-1) 6931243791Sdim Result += "\n};\n"; 6932243791Sdim else { 6933243791Sdim Result += ",\n"; 6934243791Sdim } 6935243791Sdim } 6936243791Sdim} 6937243791Sdim 6938243791Sdimstatic void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj, 6939243791Sdim ASTContext *Context, 6940243791Sdim std::string &Result, 6941243791Sdim ArrayRef<ObjCIvarDecl *> Ivars, 6942243791Sdim ObjCInterfaceDecl *CDecl) { 6943243791Sdim // FIXME. visibilty of offset symbols may have to be set; for Darwin 6944243791Sdim // this is what happens: 6945243791Sdim /** 6946243791Sdim if (Ivar->getAccessControl() == ObjCIvarDecl::Private || 6947243791Sdim Ivar->getAccessControl() == ObjCIvarDecl::Package || 6948243791Sdim Class->getVisibility() == HiddenVisibility) 6949243791Sdim Visibility shoud be: HiddenVisibility; 6950243791Sdim else 6951243791Sdim Visibility shoud be: DefaultVisibility; 6952243791Sdim */ 6953243791Sdim 6954243791Sdim Result += "\n"; 6955243791Sdim for (unsigned i =0, e = Ivars.size(); i < e; i++) { 6956243791Sdim ObjCIvarDecl *IvarDecl = Ivars[i]; 6957243791Sdim if (Context->getLangOpts().MicrosoftExt) 6958243791Sdim Result += "__declspec(allocate(\".objc_ivar$B\")) "; 6959243791Sdim 6960243791Sdim if (!Context->getLangOpts().MicrosoftExt || 6961243791Sdim IvarDecl->getAccessControl() == ObjCIvarDecl::Private || 6962243791Sdim IvarDecl->getAccessControl() == ObjCIvarDecl::Package) 6963243791Sdim Result += "extern \"C\" unsigned long int "; 6964243791Sdim else 6965243791Sdim Result += "extern \"C\" __declspec(dllexport) unsigned long int "; 6966249423Sdim if (Ivars[i]->isBitField()) 6967249423Sdim RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result); 6968249423Sdim else 6969249423Sdim WriteInternalIvarName(CDecl, IvarDecl, Result); 6970243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))"; 6971243791Sdim Result += " = "; 6972243791Sdim RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result); 6973243791Sdim Result += ";\n"; 6974249423Sdim if (Ivars[i]->isBitField()) { 6975249423Sdim // skip over rest of the ivar bitfields. 6976249423Sdim SKIP_BITFIELDS(i , e, Ivars); 6977249423Sdim } 6978243791Sdim } 6979243791Sdim} 6980243791Sdim 6981243791Sdimstatic void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj, 6982243791Sdim ASTContext *Context, std::string &Result, 6983249423Sdim ArrayRef<ObjCIvarDecl *> OriginalIvars, 6984243791Sdim StringRef VarName, 6985243791Sdim ObjCInterfaceDecl *CDecl) { 6986249423Sdim if (OriginalIvars.size() > 0) { 6987249423Sdim Write_IvarOffsetVar(RewriteObj, Context, Result, OriginalIvars, CDecl); 6988249423Sdim SmallVector<ObjCIvarDecl *, 8> Ivars; 6989249423Sdim // strip off all but the first ivar bitfield from each group of ivars. 6990249423Sdim // Such ivars in the ivar list table will be replaced by their grouping struct 6991249423Sdim // 'ivar'. 6992249423Sdim for (unsigned i = 0, e = OriginalIvars.size(); i < e; i++) { 6993249423Sdim if (OriginalIvars[i]->isBitField()) { 6994249423Sdim Ivars.push_back(OriginalIvars[i]); 6995249423Sdim // skip over rest of the ivar bitfields. 6996249423Sdim SKIP_BITFIELDS(i , e, OriginalIvars); 6997249423Sdim } 6998249423Sdim else 6999249423Sdim Ivars.push_back(OriginalIvars[i]); 7000249423Sdim } 7001243791Sdim 7002243791Sdim Result += "\nstatic "; 7003243791Sdim Write__ivar_list_t_TypeDecl(Result, Ivars.size()); 7004243791Sdim Result += " "; Result += VarName; 7005243791Sdim Result += CDecl->getNameAsString(); 7006243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 7007243791Sdim Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n"; 7008243791Sdim Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n"; 7009243791Sdim for (unsigned i =0, e = Ivars.size(); i < e; i++) { 7010243791Sdim ObjCIvarDecl *IvarDecl = Ivars[i]; 7011243791Sdim if (i == 0) 7012243791Sdim Result += "\t{{"; 7013243791Sdim else 7014243791Sdim Result += "\t {"; 7015243791Sdim Result += "(unsigned long int *)&"; 7016249423Sdim if (Ivars[i]->isBitField()) 7017249423Sdim RewriteObj.ObjCIvarBitfieldGroupOffset(IvarDecl, Result); 7018249423Sdim else 7019249423Sdim WriteInternalIvarName(CDecl, IvarDecl, Result); 7020243791Sdim Result += ", "; 7021243791Sdim 7022249423Sdim Result += "\""; 7023249423Sdim if (Ivars[i]->isBitField()) 7024249423Sdim RewriteObj.ObjCIvarBitfieldGroupDecl(Ivars[i], Result); 7025249423Sdim else 7026249423Sdim Result += IvarDecl->getName(); 7027249423Sdim Result += "\", "; 7028249423Sdim 7029249423Sdim QualType IVQT = IvarDecl->getType(); 7030249423Sdim if (IvarDecl->isBitField()) 7031249423Sdim IVQT = RewriteObj.GetGroupRecordTypeForObjCIvarBitfield(IvarDecl); 7032249423Sdim 7033243791Sdim std::string IvarTypeString, QuoteIvarTypeString; 7034249423Sdim Context->getObjCEncodingForType(IVQT, IvarTypeString, 7035243791Sdim IvarDecl); 7036243791Sdim RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString); 7037243791Sdim Result += "\""; Result += QuoteIvarTypeString; Result += "\", "; 7038243791Sdim 7039243791Sdim // FIXME. this alignment represents the host alignment and need be changed to 7040243791Sdim // represent the target alignment. 7041249423Sdim unsigned Align = Context->getTypeAlign(IVQT)/8; 7042243791Sdim Align = llvm::Log2_32(Align); 7043243791Sdim Result += llvm::utostr(Align); Result += ", "; 7044249423Sdim CharUnits Size = Context->getTypeSizeInChars(IVQT); 7045243791Sdim Result += llvm::utostr(Size.getQuantity()); 7046243791Sdim if (i == e-1) 7047243791Sdim Result += "}}\n"; 7048243791Sdim else 7049243791Sdim Result += "},\n"; 7050243791Sdim } 7051243791Sdim Result += "};\n"; 7052243791Sdim } 7053243791Sdim} 7054243791Sdim 7055243791Sdim/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. 7056243791Sdimvoid RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, 7057243791Sdim std::string &Result) { 7058243791Sdim 7059243791Sdim // Do not synthesize the protocol more than once. 7060243791Sdim if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl())) 7061243791Sdim return; 7062243791Sdim WriteModernMetadataDeclarations(Context, Result); 7063243791Sdim 7064243791Sdim if (ObjCProtocolDecl *Def = PDecl->getDefinition()) 7065243791Sdim PDecl = Def; 7066243791Sdim // Must write out all protocol definitions in current qualifier list, 7067243791Sdim // and in their nested qualifiers before writing out current definition. 7068243791Sdim for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), 7069243791Sdim E = PDecl->protocol_end(); I != E; ++I) 7070243791Sdim RewriteObjCProtocolMetaData(*I, Result); 7071243791Sdim 7072243791Sdim // Construct method lists. 7073243791Sdim std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods; 7074243791Sdim std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods; 7075243791Sdim for (ObjCProtocolDecl::instmeth_iterator 7076243791Sdim I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 7077243791Sdim I != E; ++I) { 7078243791Sdim ObjCMethodDecl *MD = *I; 7079243791Sdim if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 7080243791Sdim OptInstanceMethods.push_back(MD); 7081243791Sdim } else { 7082243791Sdim InstanceMethods.push_back(MD); 7083243791Sdim } 7084243791Sdim } 7085243791Sdim 7086243791Sdim for (ObjCProtocolDecl::classmeth_iterator 7087243791Sdim I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 7088243791Sdim I != E; ++I) { 7089243791Sdim ObjCMethodDecl *MD = *I; 7090243791Sdim if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 7091243791Sdim OptClassMethods.push_back(MD); 7092243791Sdim } else { 7093243791Sdim ClassMethods.push_back(MD); 7094243791Sdim } 7095243791Sdim } 7096243791Sdim std::vector<ObjCMethodDecl *> AllMethods; 7097243791Sdim for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++) 7098243791Sdim AllMethods.push_back(InstanceMethods[i]); 7099243791Sdim for (unsigned i = 0, e = ClassMethods.size(); i < e; i++) 7100243791Sdim AllMethods.push_back(ClassMethods[i]); 7101243791Sdim for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++) 7102243791Sdim AllMethods.push_back(OptInstanceMethods[i]); 7103243791Sdim for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++) 7104243791Sdim AllMethods.push_back(OptClassMethods[i]); 7105243791Sdim 7106243791Sdim Write__extendedMethodTypes_initializer(*this, Context, Result, 7107243791Sdim AllMethods, 7108243791Sdim "_OBJC_PROTOCOL_METHOD_TYPES_", 7109243791Sdim PDecl->getNameAsString()); 7110243791Sdim // Protocol's super protocol list 7111243791Sdim std::vector<ObjCProtocolDecl *> SuperProtocols; 7112243791Sdim for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), 7113243791Sdim E = PDecl->protocol_end(); I != E; ++I) 7114243791Sdim SuperProtocols.push_back(*I); 7115243791Sdim 7116243791Sdim Write_protocol_list_initializer(Context, Result, SuperProtocols, 7117243791Sdim "_OBJC_PROTOCOL_REFS_", 7118243791Sdim PDecl->getNameAsString()); 7119243791Sdim 7120243791Sdim Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 7121243791Sdim "_OBJC_PROTOCOL_INSTANCE_METHODS_", 7122243791Sdim PDecl->getNameAsString(), false); 7123243791Sdim 7124243791Sdim Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 7125243791Sdim "_OBJC_PROTOCOL_CLASS_METHODS_", 7126243791Sdim PDecl->getNameAsString(), false); 7127243791Sdim 7128243791Sdim Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods, 7129243791Sdim "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_", 7130243791Sdim PDecl->getNameAsString(), false); 7131243791Sdim 7132243791Sdim Write_method_list_t_initializer(*this, Context, Result, OptClassMethods, 7133243791Sdim "_OBJC_PROTOCOL_OPT_CLASS_METHODS_", 7134243791Sdim PDecl->getNameAsString(), false); 7135243791Sdim 7136243791Sdim // Protocol's property metadata. 7137243791Sdim std::vector<ObjCPropertyDecl *> ProtocolProperties; 7138243791Sdim for (ObjCContainerDecl::prop_iterator I = PDecl->prop_begin(), 7139243791Sdim E = PDecl->prop_end(); I != E; ++I) 7140243791Sdim ProtocolProperties.push_back(*I); 7141243791Sdim 7142243791Sdim Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties, 7143243791Sdim /* Container */0, 7144243791Sdim "_OBJC_PROTOCOL_PROPERTIES_", 7145243791Sdim PDecl->getNameAsString()); 7146243791Sdim 7147243791Sdim // Writer out root metadata for current protocol: struct _protocol_t 7148243791Sdim Result += "\n"; 7149243791Sdim if (LangOpts.MicrosoftExt) 7150243791Sdim Result += "static "; 7151243791Sdim Result += "struct _protocol_t _OBJC_PROTOCOL_"; 7152243791Sdim Result += PDecl->getNameAsString(); 7153243791Sdim Result += " __attribute__ ((used, section (\"__DATA,__datacoal_nt,coalesced\"))) = {\n"; 7154243791Sdim Result += "\t0,\n"; // id is; is null 7155243791Sdim Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n"; 7156243791Sdim if (SuperProtocols.size() > 0) { 7157243791Sdim Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_"; 7158243791Sdim Result += PDecl->getNameAsString(); Result += ",\n"; 7159243791Sdim } 7160243791Sdim else 7161243791Sdim Result += "\t0,\n"; 7162243791Sdim if (InstanceMethods.size() > 0) { 7163243791Sdim Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; 7164243791Sdim Result += PDecl->getNameAsString(); Result += ",\n"; 7165243791Sdim } 7166243791Sdim else 7167243791Sdim Result += "\t0,\n"; 7168243791Sdim 7169243791Sdim if (ClassMethods.size() > 0) { 7170243791Sdim Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_"; 7171243791Sdim Result += PDecl->getNameAsString(); Result += ",\n"; 7172243791Sdim } 7173243791Sdim else 7174243791Sdim Result += "\t0,\n"; 7175243791Sdim 7176243791Sdim if (OptInstanceMethods.size() > 0) { 7177243791Sdim Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_"; 7178243791Sdim Result += PDecl->getNameAsString(); Result += ",\n"; 7179243791Sdim } 7180243791Sdim else 7181243791Sdim Result += "\t0,\n"; 7182243791Sdim 7183243791Sdim if (OptClassMethods.size() > 0) { 7184243791Sdim Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_"; 7185243791Sdim Result += PDecl->getNameAsString(); Result += ",\n"; 7186243791Sdim } 7187243791Sdim else 7188243791Sdim Result += "\t0,\n"; 7189243791Sdim 7190243791Sdim if (ProtocolProperties.size() > 0) { 7191243791Sdim Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_"; 7192243791Sdim Result += PDecl->getNameAsString(); Result += ",\n"; 7193243791Sdim } 7194243791Sdim else 7195243791Sdim Result += "\t0,\n"; 7196243791Sdim 7197243791Sdim Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n"; 7198243791Sdim Result += "\t0,\n"; 7199243791Sdim 7200243791Sdim if (AllMethods.size() > 0) { 7201243791Sdim Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_"; 7202243791Sdim Result += PDecl->getNameAsString(); 7203243791Sdim Result += "\n};\n"; 7204243791Sdim } 7205243791Sdim else 7206243791Sdim Result += "\t0\n};\n"; 7207243791Sdim 7208243791Sdim if (LangOpts.MicrosoftExt) 7209243791Sdim Result += "static "; 7210243791Sdim Result += "struct _protocol_t *"; 7211243791Sdim Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString(); 7212243791Sdim Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString(); 7213243791Sdim Result += ";\n"; 7214243791Sdim 7215243791Sdim // Mark this protocol as having been generated. 7216243791Sdim if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl())) 7217243791Sdim llvm_unreachable("protocol already synthesized"); 7218243791Sdim 7219243791Sdim} 7220243791Sdim 7221243791Sdimvoid RewriteModernObjC::RewriteObjCProtocolListMetaData( 7222243791Sdim const ObjCList<ObjCProtocolDecl> &Protocols, 7223243791Sdim StringRef prefix, StringRef ClassName, 7224243791Sdim std::string &Result) { 7225243791Sdim if (Protocols.empty()) return; 7226243791Sdim 7227243791Sdim for (unsigned i = 0; i != Protocols.size(); i++) 7228243791Sdim RewriteObjCProtocolMetaData(Protocols[i], Result); 7229243791Sdim 7230243791Sdim // Output the top lovel protocol meta-data for the class. 7231243791Sdim /* struct _objc_protocol_list { 7232243791Sdim struct _objc_protocol_list *next; 7233243791Sdim int protocol_count; 7234243791Sdim struct _objc_protocol *class_protocols[]; 7235243791Sdim } 7236243791Sdim */ 7237243791Sdim Result += "\n"; 7238243791Sdim if (LangOpts.MicrosoftExt) 7239243791Sdim Result += "__declspec(allocate(\".cat_cls_meth$B\")) "; 7240243791Sdim Result += "static struct {\n"; 7241243791Sdim Result += "\tstruct _objc_protocol_list *next;\n"; 7242243791Sdim Result += "\tint protocol_count;\n"; 7243243791Sdim Result += "\tstruct _objc_protocol *class_protocols["; 7244243791Sdim Result += utostr(Protocols.size()); 7245243791Sdim Result += "];\n} _OBJC_"; 7246243791Sdim Result += prefix; 7247243791Sdim Result += "_PROTOCOLS_"; 7248243791Sdim Result += ClassName; 7249243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 7250243791Sdim "{\n\t0, "; 7251243791Sdim Result += utostr(Protocols.size()); 7252243791Sdim Result += "\n"; 7253243791Sdim 7254243791Sdim Result += "\t,{&_OBJC_PROTOCOL_"; 7255243791Sdim Result += Protocols[0]->getNameAsString(); 7256243791Sdim Result += " \n"; 7257243791Sdim 7258243791Sdim for (unsigned i = 1; i != Protocols.size(); i++) { 7259243791Sdim Result += "\t ,&_OBJC_PROTOCOL_"; 7260243791Sdim Result += Protocols[i]->getNameAsString(); 7261243791Sdim Result += "\n"; 7262243791Sdim } 7263243791Sdim Result += "\t }\n};\n"; 7264243791Sdim} 7265243791Sdim 7266243791Sdim/// hasObjCExceptionAttribute - Return true if this class or any super 7267243791Sdim/// class has the __objc_exception__ attribute. 7268243791Sdim/// FIXME. Move this to ASTContext.cpp as it is also used for IRGen. 7269243791Sdimstatic bool hasObjCExceptionAttribute(ASTContext &Context, 7270243791Sdim const ObjCInterfaceDecl *OID) { 7271243791Sdim if (OID->hasAttr<ObjCExceptionAttr>()) 7272243791Sdim return true; 7273243791Sdim if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 7274243791Sdim return hasObjCExceptionAttribute(Context, Super); 7275243791Sdim return false; 7276243791Sdim} 7277243791Sdim 7278243791Sdimvoid RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 7279243791Sdim std::string &Result) { 7280243791Sdim ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 7281243791Sdim 7282243791Sdim // Explicitly declared @interface's are already synthesized. 7283243791Sdim if (CDecl->isImplicitInterfaceDecl()) 7284243791Sdim assert(false && 7285243791Sdim "Legacy implicit interface rewriting not supported in moder abi"); 7286243791Sdim 7287243791Sdim WriteModernMetadataDeclarations(Context, Result); 7288243791Sdim SmallVector<ObjCIvarDecl *, 8> IVars; 7289243791Sdim 7290243791Sdim for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 7291243791Sdim IVD; IVD = IVD->getNextIvar()) { 7292243791Sdim // Ignore unnamed bit-fields. 7293243791Sdim if (!IVD->getDeclName()) 7294243791Sdim continue; 7295243791Sdim IVars.push_back(IVD); 7296243791Sdim } 7297243791Sdim 7298243791Sdim Write__ivar_list_t_initializer(*this, Context, Result, IVars, 7299243791Sdim "_OBJC_$_INSTANCE_VARIABLES_", 7300243791Sdim CDecl); 7301243791Sdim 7302243791Sdim // Build _objc_method_list for class's instance methods if needed 7303243791Sdim SmallVector<ObjCMethodDecl *, 32> 7304243791Sdim InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 7305243791Sdim 7306243791Sdim // If any of our property implementations have associated getters or 7307243791Sdim // setters, produce metadata for them as well. 7308243791Sdim for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 7309243791Sdim PropEnd = IDecl->propimpl_end(); 7310243791Sdim Prop != PropEnd; ++Prop) { 7311243791Sdim if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 7312243791Sdim continue; 7313243791Sdim if (!Prop->getPropertyIvarDecl()) 7314243791Sdim continue; 7315243791Sdim ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 7316243791Sdim if (!PD) 7317243791Sdim continue; 7318243791Sdim if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 7319243791Sdim if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/)) 7320243791Sdim InstanceMethods.push_back(Getter); 7321243791Sdim if (PD->isReadOnly()) 7322243791Sdim continue; 7323243791Sdim if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 7324243791Sdim if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/)) 7325243791Sdim InstanceMethods.push_back(Setter); 7326243791Sdim } 7327243791Sdim 7328243791Sdim Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 7329243791Sdim "_OBJC_$_INSTANCE_METHODS_", 7330243791Sdim IDecl->getNameAsString(), true); 7331243791Sdim 7332243791Sdim SmallVector<ObjCMethodDecl *, 32> 7333243791Sdim ClassMethods(IDecl->classmeth_begin(), IDecl->classmeth_end()); 7334243791Sdim 7335243791Sdim Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 7336243791Sdim "_OBJC_$_CLASS_METHODS_", 7337243791Sdim IDecl->getNameAsString(), true); 7338243791Sdim 7339243791Sdim // Protocols referenced in class declaration? 7340243791Sdim // Protocol's super protocol list 7341243791Sdim std::vector<ObjCProtocolDecl *> RefedProtocols; 7342243791Sdim const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols(); 7343243791Sdim for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 7344243791Sdim E = Protocols.end(); 7345243791Sdim I != E; ++I) { 7346243791Sdim RefedProtocols.push_back(*I); 7347243791Sdim // Must write out all protocol definitions in current qualifier list, 7348243791Sdim // and in their nested qualifiers before writing out current definition. 7349243791Sdim RewriteObjCProtocolMetaData(*I, Result); 7350243791Sdim } 7351243791Sdim 7352243791Sdim Write_protocol_list_initializer(Context, Result, 7353243791Sdim RefedProtocols, 7354243791Sdim "_OBJC_CLASS_PROTOCOLS_$_", 7355243791Sdim IDecl->getNameAsString()); 7356243791Sdim 7357243791Sdim // Protocol's property metadata. 7358243791Sdim std::vector<ObjCPropertyDecl *> ClassProperties; 7359243791Sdim for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), 7360243791Sdim E = CDecl->prop_end(); I != E; ++I) 7361243791Sdim ClassProperties.push_back(*I); 7362243791Sdim 7363243791Sdim Write_prop_list_t_initializer(*this, Context, Result, ClassProperties, 7364243791Sdim /* Container */IDecl, 7365243791Sdim "_OBJC_$_PROP_LIST_", 7366243791Sdim CDecl->getNameAsString()); 7367243791Sdim 7368243791Sdim 7369243791Sdim // Data for initializing _class_ro_t metaclass meta-data 7370243791Sdim uint32_t flags = CLS_META; 7371243791Sdim std::string InstanceSize; 7372243791Sdim std::string InstanceStart; 7373243791Sdim 7374243791Sdim 7375243791Sdim bool classIsHidden = CDecl->getVisibility() == HiddenVisibility; 7376243791Sdim if (classIsHidden) 7377243791Sdim flags |= OBJC2_CLS_HIDDEN; 7378243791Sdim 7379243791Sdim if (!CDecl->getSuperClass()) 7380243791Sdim // class is root 7381243791Sdim flags |= CLS_ROOT; 7382243791Sdim InstanceSize = "sizeof(struct _class_t)"; 7383243791Sdim InstanceStart = InstanceSize; 7384243791Sdim Write__class_ro_t_initializer(Context, Result, flags, 7385243791Sdim InstanceStart, InstanceSize, 7386243791Sdim ClassMethods, 7387243791Sdim 0, 7388243791Sdim 0, 7389243791Sdim 0, 7390243791Sdim "_OBJC_METACLASS_RO_$_", 7391243791Sdim CDecl->getNameAsString()); 7392243791Sdim 7393243791Sdim 7394243791Sdim // Data for initializing _class_ro_t meta-data 7395243791Sdim flags = CLS; 7396243791Sdim if (classIsHidden) 7397243791Sdim flags |= OBJC2_CLS_HIDDEN; 7398243791Sdim 7399243791Sdim if (hasObjCExceptionAttribute(*Context, CDecl)) 7400243791Sdim flags |= CLS_EXCEPTION; 7401243791Sdim 7402243791Sdim if (!CDecl->getSuperClass()) 7403243791Sdim // class is root 7404243791Sdim flags |= CLS_ROOT; 7405243791Sdim 7406243791Sdim InstanceSize.clear(); 7407243791Sdim InstanceStart.clear(); 7408243791Sdim if (!ObjCSynthesizedStructs.count(CDecl)) { 7409243791Sdim InstanceSize = "0"; 7410243791Sdim InstanceStart = "0"; 7411243791Sdim } 7412243791Sdim else { 7413243791Sdim InstanceSize = "sizeof(struct "; 7414243791Sdim InstanceSize += CDecl->getNameAsString(); 7415243791Sdim InstanceSize += "_IMPL)"; 7416243791Sdim 7417243791Sdim ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 7418243791Sdim if (IVD) { 7419243791Sdim RewriteIvarOffsetComputation(IVD, InstanceStart); 7420243791Sdim } 7421243791Sdim else 7422243791Sdim InstanceStart = InstanceSize; 7423243791Sdim } 7424243791Sdim Write__class_ro_t_initializer(Context, Result, flags, 7425243791Sdim InstanceStart, InstanceSize, 7426243791Sdim InstanceMethods, 7427243791Sdim RefedProtocols, 7428243791Sdim IVars, 7429243791Sdim ClassProperties, 7430243791Sdim "_OBJC_CLASS_RO_$_", 7431243791Sdim CDecl->getNameAsString()); 7432243791Sdim 7433243791Sdim Write_class_t(Context, Result, 7434243791Sdim "OBJC_METACLASS_$_", 7435243791Sdim CDecl, /*metaclass*/true); 7436243791Sdim 7437243791Sdim Write_class_t(Context, Result, 7438243791Sdim "OBJC_CLASS_$_", 7439243791Sdim CDecl, /*metaclass*/false); 7440243791Sdim 7441243791Sdim if (ImplementationIsNonLazy(IDecl)) 7442243791Sdim DefinedNonLazyClasses.push_back(CDecl); 7443243791Sdim 7444243791Sdim} 7445243791Sdim 7446243791Sdimvoid RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) { 7447243791Sdim int ClsDefCount = ClassImplementation.size(); 7448243791Sdim if (!ClsDefCount) 7449243791Sdim return; 7450243791Sdim Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n"; 7451243791Sdim Result += "__declspec(allocate(\".objc_inithooks$B\")) "; 7452243791Sdim Result += "static void *OBJC_CLASS_SETUP[] = {\n"; 7453243791Sdim for (int i = 0; i < ClsDefCount; i++) { 7454243791Sdim ObjCImplementationDecl *IDecl = ClassImplementation[i]; 7455243791Sdim ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 7456243791Sdim Result += "\t(void *)&OBJC_CLASS_SETUP_$_"; 7457243791Sdim Result += CDecl->getName(); Result += ",\n"; 7458243791Sdim } 7459243791Sdim Result += "};\n"; 7460243791Sdim} 7461243791Sdim 7462243791Sdimvoid RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) { 7463243791Sdim int ClsDefCount = ClassImplementation.size(); 7464243791Sdim int CatDefCount = CategoryImplementation.size(); 7465243791Sdim 7466243791Sdim // For each implemented class, write out all its meta data. 7467243791Sdim for (int i = 0; i < ClsDefCount; i++) 7468243791Sdim RewriteObjCClassMetaData(ClassImplementation[i], Result); 7469243791Sdim 7470243791Sdim RewriteClassSetupInitHook(Result); 7471243791Sdim 7472243791Sdim // For each implemented category, write out all its meta data. 7473243791Sdim for (int i = 0; i < CatDefCount; i++) 7474243791Sdim RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); 7475243791Sdim 7476243791Sdim RewriteCategorySetupInitHook(Result); 7477243791Sdim 7478243791Sdim if (ClsDefCount > 0) { 7479243791Sdim if (LangOpts.MicrosoftExt) 7480243791Sdim Result += "__declspec(allocate(\".objc_classlist$B\")) "; 7481243791Sdim Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ ["; 7482243791Sdim Result += llvm::utostr(ClsDefCount); Result += "]"; 7483243791Sdim Result += 7484243791Sdim " __attribute__((used, section (\"__DATA, __objc_classlist," 7485243791Sdim "regular,no_dead_strip\")))= {\n"; 7486243791Sdim for (int i = 0; i < ClsDefCount; i++) { 7487243791Sdim Result += "\t&OBJC_CLASS_$_"; 7488243791Sdim Result += ClassImplementation[i]->getNameAsString(); 7489243791Sdim Result += ",\n"; 7490243791Sdim } 7491243791Sdim Result += "};\n"; 7492243791Sdim 7493243791Sdim if (!DefinedNonLazyClasses.empty()) { 7494243791Sdim if (LangOpts.MicrosoftExt) 7495243791Sdim Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n"; 7496243791Sdim Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t"; 7497243791Sdim for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) { 7498243791Sdim Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString(); 7499243791Sdim Result += ",\n"; 7500243791Sdim } 7501243791Sdim Result += "};\n"; 7502243791Sdim } 7503243791Sdim } 7504243791Sdim 7505243791Sdim if (CatDefCount > 0) { 7506243791Sdim if (LangOpts.MicrosoftExt) 7507243791Sdim Result += "__declspec(allocate(\".objc_catlist$B\")) "; 7508243791Sdim Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ ["; 7509243791Sdim Result += llvm::utostr(CatDefCount); Result += "]"; 7510243791Sdim Result += 7511243791Sdim " __attribute__((used, section (\"__DATA, __objc_catlist," 7512243791Sdim "regular,no_dead_strip\")))= {\n"; 7513243791Sdim for (int i = 0; i < CatDefCount; i++) { 7514243791Sdim Result += "\t&_OBJC_$_CATEGORY_"; 7515243791Sdim Result += 7516243791Sdim CategoryImplementation[i]->getClassInterface()->getNameAsString(); 7517243791Sdim Result += "_$_"; 7518243791Sdim Result += CategoryImplementation[i]->getNameAsString(); 7519243791Sdim Result += ",\n"; 7520243791Sdim } 7521243791Sdim Result += "};\n"; 7522243791Sdim } 7523243791Sdim 7524243791Sdim if (!DefinedNonLazyCategories.empty()) { 7525243791Sdim if (LangOpts.MicrosoftExt) 7526243791Sdim Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n"; 7527243791Sdim Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t"; 7528243791Sdim for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) { 7529243791Sdim Result += "\t&_OBJC_$_CATEGORY_"; 7530243791Sdim Result += 7531243791Sdim DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString(); 7532243791Sdim Result += "_$_"; 7533243791Sdim Result += DefinedNonLazyCategories[i]->getNameAsString(); 7534243791Sdim Result += ",\n"; 7535243791Sdim } 7536243791Sdim Result += "};\n"; 7537243791Sdim } 7538243791Sdim} 7539243791Sdim 7540243791Sdimvoid RewriteModernObjC::WriteImageInfo(std::string &Result) { 7541243791Sdim if (LangOpts.MicrosoftExt) 7542243791Sdim Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n"; 7543243791Sdim 7544243791Sdim Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } "; 7545243791Sdim // version 0, ObjCABI is 2 7546243791Sdim Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n"; 7547243791Sdim} 7548243791Sdim 7549243791Sdim/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category 7550243791Sdim/// implementation. 7551243791Sdimvoid RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, 7552243791Sdim std::string &Result) { 7553243791Sdim WriteModernMetadataDeclarations(Context, Result); 7554243791Sdim ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 7555243791Sdim // Find category declaration for this implementation. 7556249423Sdim ObjCCategoryDecl *CDecl 7557249423Sdim = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier()); 7558243791Sdim 7559243791Sdim std::string FullCategoryName = ClassDecl->getNameAsString(); 7560243791Sdim FullCategoryName += "_$_"; 7561243791Sdim FullCategoryName += CDecl->getNameAsString(); 7562243791Sdim 7563243791Sdim // Build _objc_method_list for class's instance methods if needed 7564243791Sdim SmallVector<ObjCMethodDecl *, 32> 7565243791Sdim InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 7566243791Sdim 7567243791Sdim // If any of our property implementations have associated getters or 7568243791Sdim // setters, produce metadata for them as well. 7569243791Sdim for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 7570243791Sdim PropEnd = IDecl->propimpl_end(); 7571243791Sdim Prop != PropEnd; ++Prop) { 7572243791Sdim if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 7573243791Sdim continue; 7574243791Sdim if (!Prop->getPropertyIvarDecl()) 7575243791Sdim continue; 7576243791Sdim ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 7577243791Sdim if (!PD) 7578243791Sdim continue; 7579243791Sdim if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 7580243791Sdim InstanceMethods.push_back(Getter); 7581243791Sdim if (PD->isReadOnly()) 7582243791Sdim continue; 7583243791Sdim if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 7584243791Sdim InstanceMethods.push_back(Setter); 7585243791Sdim } 7586243791Sdim 7587243791Sdim Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 7588243791Sdim "_OBJC_$_CATEGORY_INSTANCE_METHODS_", 7589243791Sdim FullCategoryName, true); 7590243791Sdim 7591243791Sdim SmallVector<ObjCMethodDecl *, 32> 7592243791Sdim ClassMethods(IDecl->classmeth_begin(), IDecl->classmeth_end()); 7593243791Sdim 7594243791Sdim Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 7595243791Sdim "_OBJC_$_CATEGORY_CLASS_METHODS_", 7596243791Sdim FullCategoryName, true); 7597243791Sdim 7598243791Sdim // Protocols referenced in class declaration? 7599243791Sdim // Protocol's super protocol list 7600243791Sdim std::vector<ObjCProtocolDecl *> RefedProtocols; 7601243791Sdim for (ObjCInterfaceDecl::protocol_iterator I = CDecl->protocol_begin(), 7602243791Sdim E = CDecl->protocol_end(); 7603243791Sdim 7604243791Sdim I != E; ++I) { 7605243791Sdim RefedProtocols.push_back(*I); 7606243791Sdim // Must write out all protocol definitions in current qualifier list, 7607243791Sdim // and in their nested qualifiers before writing out current definition. 7608243791Sdim RewriteObjCProtocolMetaData(*I, Result); 7609243791Sdim } 7610243791Sdim 7611243791Sdim Write_protocol_list_initializer(Context, Result, 7612243791Sdim RefedProtocols, 7613243791Sdim "_OBJC_CATEGORY_PROTOCOLS_$_", 7614243791Sdim FullCategoryName); 7615243791Sdim 7616243791Sdim // Protocol's property metadata. 7617243791Sdim std::vector<ObjCPropertyDecl *> ClassProperties; 7618243791Sdim for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), 7619243791Sdim E = CDecl->prop_end(); I != E; ++I) 7620243791Sdim ClassProperties.push_back(*I); 7621243791Sdim 7622243791Sdim Write_prop_list_t_initializer(*this, Context, Result, ClassProperties, 7623243791Sdim /* Container */IDecl, 7624243791Sdim "_OBJC_$_PROP_LIST_", 7625243791Sdim FullCategoryName); 7626243791Sdim 7627243791Sdim Write_category_t(*this, Context, Result, 7628243791Sdim CDecl, 7629243791Sdim ClassDecl, 7630243791Sdim InstanceMethods, 7631243791Sdim ClassMethods, 7632243791Sdim RefedProtocols, 7633243791Sdim ClassProperties); 7634243791Sdim 7635243791Sdim // Determine if this category is also "non-lazy". 7636243791Sdim if (ImplementationIsNonLazy(IDecl)) 7637243791Sdim DefinedNonLazyCategories.push_back(CDecl); 7638243791Sdim 7639243791Sdim} 7640243791Sdim 7641243791Sdimvoid RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) { 7642243791Sdim int CatDefCount = CategoryImplementation.size(); 7643243791Sdim if (!CatDefCount) 7644243791Sdim return; 7645243791Sdim Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n"; 7646243791Sdim Result += "__declspec(allocate(\".objc_inithooks$B\")) "; 7647243791Sdim Result += "static void *OBJC_CATEGORY_SETUP[] = {\n"; 7648243791Sdim for (int i = 0; i < CatDefCount; i++) { 7649243791Sdim ObjCCategoryImplDecl *IDecl = CategoryImplementation[i]; 7650243791Sdim ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl(); 7651243791Sdim ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 7652243791Sdim Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_"; 7653243791Sdim Result += ClassDecl->getName(); 7654243791Sdim Result += "_$_"; 7655243791Sdim Result += CatDecl->getName(); 7656243791Sdim Result += ",\n"; 7657243791Sdim } 7658243791Sdim Result += "};\n"; 7659243791Sdim} 7660243791Sdim 7661243791Sdim// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or 7662243791Sdim/// class methods. 7663243791Sdimtemplate<typename MethodIterator> 7664243791Sdimvoid RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 7665243791Sdim MethodIterator MethodEnd, 7666243791Sdim bool IsInstanceMethod, 7667243791Sdim StringRef prefix, 7668243791Sdim StringRef ClassName, 7669243791Sdim std::string &Result) { 7670243791Sdim if (MethodBegin == MethodEnd) return; 7671243791Sdim 7672243791Sdim if (!objc_impl_method) { 7673243791Sdim /* struct _objc_method { 7674243791Sdim SEL _cmd; 7675243791Sdim char *method_types; 7676243791Sdim void *_imp; 7677243791Sdim } 7678243791Sdim */ 7679243791Sdim Result += "\nstruct _objc_method {\n"; 7680243791Sdim Result += "\tSEL _cmd;\n"; 7681243791Sdim Result += "\tchar *method_types;\n"; 7682243791Sdim Result += "\tvoid *_imp;\n"; 7683243791Sdim Result += "};\n"; 7684243791Sdim 7685243791Sdim objc_impl_method = true; 7686243791Sdim } 7687243791Sdim 7688243791Sdim // Build _objc_method_list for class's methods if needed 7689243791Sdim 7690243791Sdim /* struct { 7691243791Sdim struct _objc_method_list *next_method; 7692243791Sdim int method_count; 7693243791Sdim struct _objc_method method_list[]; 7694243791Sdim } 7695243791Sdim */ 7696243791Sdim unsigned NumMethods = std::distance(MethodBegin, MethodEnd); 7697243791Sdim Result += "\n"; 7698243791Sdim if (LangOpts.MicrosoftExt) { 7699243791Sdim if (IsInstanceMethod) 7700243791Sdim Result += "__declspec(allocate(\".inst_meth$B\")) "; 7701243791Sdim else 7702243791Sdim Result += "__declspec(allocate(\".cls_meth$B\")) "; 7703243791Sdim } 7704243791Sdim Result += "static struct {\n"; 7705243791Sdim Result += "\tstruct _objc_method_list *next_method;\n"; 7706243791Sdim Result += "\tint method_count;\n"; 7707243791Sdim Result += "\tstruct _objc_method method_list["; 7708243791Sdim Result += utostr(NumMethods); 7709243791Sdim Result += "];\n} _OBJC_"; 7710243791Sdim Result += prefix; 7711243791Sdim Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; 7712243791Sdim Result += "_METHODS_"; 7713243791Sdim Result += ClassName; 7714243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __"; 7715243791Sdim Result += IsInstanceMethod ? "inst" : "cls"; 7716243791Sdim Result += "_meth\")))= "; 7717243791Sdim Result += "{\n\t0, " + utostr(NumMethods) + "\n"; 7718243791Sdim 7719243791Sdim Result += "\t,{{(SEL)\""; 7720243791Sdim Result += (*MethodBegin)->getSelector().getAsString().c_str(); 7721243791Sdim std::string MethodTypeString; 7722243791Sdim Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 7723243791Sdim Result += "\", \""; 7724243791Sdim Result += MethodTypeString; 7725243791Sdim Result += "\", (void *)"; 7726243791Sdim Result += MethodInternalNames[*MethodBegin]; 7727243791Sdim Result += "}\n"; 7728243791Sdim for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { 7729243791Sdim Result += "\t ,{(SEL)\""; 7730243791Sdim Result += (*MethodBegin)->getSelector().getAsString().c_str(); 7731243791Sdim std::string MethodTypeString; 7732243791Sdim Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 7733243791Sdim Result += "\", \""; 7734243791Sdim Result += MethodTypeString; 7735243791Sdim Result += "\", (void *)"; 7736243791Sdim Result += MethodInternalNames[*MethodBegin]; 7737243791Sdim Result += "}\n"; 7738243791Sdim } 7739243791Sdim Result += "\t }\n};\n"; 7740243791Sdim} 7741243791Sdim 7742243791SdimStmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { 7743243791Sdim SourceRange OldRange = IV->getSourceRange(); 7744243791Sdim Expr *BaseExpr = IV->getBase(); 7745243791Sdim 7746243791Sdim // Rewrite the base, but without actually doing replaces. 7747243791Sdim { 7748243791Sdim DisableReplaceStmtScope S(*this); 7749243791Sdim BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr)); 7750243791Sdim IV->setBase(BaseExpr); 7751243791Sdim } 7752243791Sdim 7753243791Sdim ObjCIvarDecl *D = IV->getDecl(); 7754243791Sdim 7755243791Sdim Expr *Replacement = IV; 7756243791Sdim 7757243791Sdim if (BaseExpr->getType()->isObjCObjectPointerType()) { 7758243791Sdim const ObjCInterfaceType *iFaceDecl = 7759243791Sdim dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 7760243791Sdim assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); 7761243791Sdim // lookup which class implements the instance variable. 7762243791Sdim ObjCInterfaceDecl *clsDeclared = 0; 7763243791Sdim iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 7764243791Sdim clsDeclared); 7765243791Sdim assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 7766243791Sdim 7767243791Sdim // Build name of symbol holding ivar offset. 7768243791Sdim std::string IvarOffsetName; 7769249423Sdim if (D->isBitField()) 7770249423Sdim ObjCIvarBitfieldGroupOffset(D, IvarOffsetName); 7771249423Sdim else 7772249423Sdim WriteInternalIvarName(clsDeclared, D, IvarOffsetName); 7773243791Sdim 7774243791Sdim ReferencedIvars[clsDeclared].insert(D); 7775243791Sdim 7776243791Sdim // cast offset to "char *". 7777243791Sdim CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, 7778243791Sdim Context->getPointerType(Context->CharTy), 7779243791Sdim CK_BitCast, 7780243791Sdim BaseExpr); 7781243791Sdim VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 7782243791Sdim SourceLocation(), &Context->Idents.get(IvarOffsetName), 7783249423Sdim Context->UnsignedLongTy, 0, SC_Extern); 7784243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, 7785243791Sdim Context->UnsignedLongTy, VK_LValue, 7786243791Sdim SourceLocation()); 7787243791Sdim BinaryOperator *addExpr = 7788243791Sdim new (Context) BinaryOperator(castExpr, DRE, BO_Add, 7789243791Sdim Context->getPointerType(Context->CharTy), 7790243791Sdim VK_RValue, OK_Ordinary, SourceLocation(), false); 7791243791Sdim // Don't forget the parens to enforce the proper binding. 7792243791Sdim ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), 7793243791Sdim SourceLocation(), 7794243791Sdim addExpr); 7795243791Sdim QualType IvarT = D->getType(); 7796249423Sdim if (D->isBitField()) 7797249423Sdim IvarT = GetGroupRecordTypeForObjCIvarBitfield(D); 7798243791Sdim 7799243791Sdim if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) { 7800243791Sdim RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl(); 7801243791Sdim RD = RD->getDefinition(); 7802243791Sdim if (RD && !RD->getDeclName().getAsIdentifierInfo()) { 7803243791Sdim // decltype(((Foo_IMPL*)0)->bar) * 7804243791Sdim ObjCContainerDecl *CDecl = 7805243791Sdim dyn_cast<ObjCContainerDecl>(D->getDeclContext()); 7806243791Sdim // ivar in class extensions requires special treatment. 7807243791Sdim if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 7808243791Sdim CDecl = CatDecl->getClassInterface(); 7809243791Sdim std::string RecName = CDecl->getName(); 7810243791Sdim RecName += "_IMPL"; 7811243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 7812243791Sdim SourceLocation(), SourceLocation(), 7813243791Sdim &Context->Idents.get(RecName.c_str())); 7814243791Sdim QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD)); 7815243791Sdim unsigned UnsignedIntSize = 7816243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 7817243791Sdim Expr *Zero = IntegerLiteral::Create(*Context, 7818243791Sdim llvm::APInt(UnsignedIntSize, 0), 7819243791Sdim Context->UnsignedIntTy, SourceLocation()); 7820243791Sdim Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero); 7821243791Sdim ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 7822243791Sdim Zero); 7823243791Sdim FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 7824243791Sdim SourceLocation(), 7825243791Sdim &Context->Idents.get(D->getNameAsString()), 7826243791Sdim IvarT, 0, 7827243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 7828243791Sdim ICIS_NoInit); 7829243791Sdim MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 7830243791Sdim FD->getType(), VK_LValue, 7831243791Sdim OK_Ordinary); 7832243791Sdim IvarT = Context->getDecltypeType(ME, ME->getType()); 7833243791Sdim } 7834243791Sdim } 7835243791Sdim convertObjCTypeToCStyleType(IvarT); 7836243791Sdim QualType castT = Context->getPointerType(IvarT); 7837243791Sdim 7838243791Sdim castExpr = NoTypeInfoCStyleCastExpr(Context, 7839243791Sdim castT, 7840243791Sdim CK_BitCast, 7841243791Sdim PE); 7842243791Sdim 7843243791Sdim 7844243791Sdim Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, IvarT, 7845243791Sdim VK_LValue, OK_Ordinary, 7846243791Sdim SourceLocation()); 7847243791Sdim PE = new (Context) ParenExpr(OldRange.getBegin(), 7848243791Sdim OldRange.getEnd(), 7849243791Sdim Exp); 7850249423Sdim 7851249423Sdim if (D->isBitField()) { 7852249423Sdim FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 7853249423Sdim SourceLocation(), 7854249423Sdim &Context->Idents.get(D->getNameAsString()), 7855249423Sdim D->getType(), 0, 7856249423Sdim /*BitWidth=*/D->getBitWidth(), 7857249423Sdim /*Mutable=*/true, 7858249423Sdim ICIS_NoInit); 7859249423Sdim MemberExpr *ME = new (Context) MemberExpr(PE, /*isArrow*/false, FD, SourceLocation(), 7860249423Sdim FD->getType(), VK_LValue, 7861249423Sdim OK_Ordinary); 7862249423Sdim Replacement = ME; 7863243791Sdim 7864249423Sdim } 7865249423Sdim else 7866249423Sdim Replacement = PE; 7867243791Sdim } 7868243791Sdim 7869243791Sdim ReplaceStmtWithRange(IV, Replacement, OldRange); 7870243791Sdim return Replacement; 7871243791Sdim} 7872