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" 23243791Sdim#include "clang/Lex/Lexer.h" 24249423Sdim#include "clang/Rewrite/Core/Rewriter.h" 25249423Sdim#include "llvm/ADT/DenseSet.h" 26249423Sdim#include "llvm/ADT/OwningPtr.h" 27249423Sdim#include "llvm/ADT/SmallPtrSet.h" 28249423Sdim#include "llvm/ADT/StringExtras.h" 29243791Sdim#include "llvm/Support/MemoryBuffer.h" 30243791Sdim#include "llvm/Support/raw_ostream.h" 31243791Sdim 32243791Sdimusing namespace clang; 33243791Sdimusing llvm::utostr; 34243791Sdim 35243791Sdimnamespace { 36243791Sdim class RewriteObjC : public ASTConsumer { 37243791Sdim protected: 38243791Sdim 39243791Sdim enum { 40243791Sdim BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 41243791Sdim block, ... */ 42243791Sdim BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 43243791Sdim BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the 44243791Sdim __block variable */ 45243791Sdim BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 46243791Sdim helpers */ 47243791Sdim BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 48243791Sdim support routines */ 49243791Sdim BLOCK_BYREF_CURRENT_MAX = 256 50243791Sdim }; 51243791Sdim 52243791Sdim enum { 53243791Sdim BLOCK_NEEDS_FREE = (1 << 24), 54243791Sdim BLOCK_HAS_COPY_DISPOSE = (1 << 25), 55243791Sdim BLOCK_HAS_CXX_OBJ = (1 << 26), 56243791Sdim BLOCK_IS_GC = (1 << 27), 57243791Sdim BLOCK_IS_GLOBAL = (1 << 28), 58243791Sdim BLOCK_HAS_DESCRIPTOR = (1 << 29) 59243791Sdim }; 60243791Sdim static const int OBJC_ABI_VERSION = 7; 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 unsigned RewriteFailedDiag; 79243791Sdim // ObjC string constant support. 80243791Sdim unsigned NumObjCStringLiterals; 81243791Sdim VarDecl *ConstantStringClassReference; 82243791Sdim RecordDecl *NSStringRecord; 83243791Sdim 84243791Sdim // ObjC foreach break/continue generation support. 85243791Sdim int BcLabelCount; 86243791Sdim 87243791Sdim unsigned TryFinallyContainsReturnDiag; 88243791Sdim // Needed for super. 89243791Sdim ObjCMethodDecl *CurMethodDef; 90243791Sdim RecordDecl *SuperStructDecl; 91243791Sdim RecordDecl *ConstantStringDecl; 92243791Sdim 93243791Sdim FunctionDecl *MsgSendFunctionDecl; 94243791Sdim FunctionDecl *MsgSendSuperFunctionDecl; 95243791Sdim FunctionDecl *MsgSendStretFunctionDecl; 96243791Sdim FunctionDecl *MsgSendSuperStretFunctionDecl; 97243791Sdim FunctionDecl *MsgSendFpretFunctionDecl; 98243791Sdim FunctionDecl *GetClassFunctionDecl; 99243791Sdim FunctionDecl *GetMetaClassFunctionDecl; 100243791Sdim FunctionDecl *GetSuperClassFunctionDecl; 101243791Sdim FunctionDecl *SelGetUidFunctionDecl; 102243791Sdim FunctionDecl *CFStringFunctionDecl; 103263508Sdim FunctionDecl *SuperConstructorFunctionDecl; 104243791Sdim FunctionDecl *CurFunctionDef; 105243791Sdim FunctionDecl *CurFunctionDeclToDeclareForBlock; 106243791Sdim 107243791Sdim /* Misc. containers needed for meta-data rewrite. */ 108243791Sdim SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; 109243791Sdim SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; 110243791Sdim llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; 111243791Sdim llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; 112243791Sdim llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls; 113243791Sdim llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; 114243791Sdim SmallVector<Stmt *, 32> Stmts; 115243791Sdim SmallVector<int, 8> ObjCBcLabelNo; 116243791Sdim // Remember all the @protocol(<expr>) expressions. 117243791Sdim llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; 118243791Sdim 119243791Sdim llvm::DenseSet<uint64_t> CopyDestroyCache; 120243791Sdim 121243791Sdim // Block expressions. 122243791Sdim SmallVector<BlockExpr *, 32> Blocks; 123243791Sdim SmallVector<int, 32> InnerDeclRefsCount; 124243791Sdim SmallVector<DeclRefExpr *, 32> InnerDeclRefs; 125243791Sdim 126243791Sdim SmallVector<DeclRefExpr *, 32> BlockDeclRefs; 127243791Sdim 128243791Sdim // Block related declarations. 129243791Sdim SmallVector<ValueDecl *, 8> BlockByCopyDecls; 130243791Sdim llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; 131243791Sdim SmallVector<ValueDecl *, 8> BlockByRefDecls; 132243791Sdim llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; 133243791Sdim llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; 134243791Sdim llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; 135243791Sdim llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls; 136243791Sdim 137243791Sdim llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; 138243791Sdim 139243791Sdim // This maps an original source AST to it's rewritten form. This allows 140243791Sdim // us to avoid rewriting the same node twice (which is very uncommon). 141243791Sdim // This is needed to support some of the exotic property rewriting. 142243791Sdim llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; 143243791Sdim 144243791Sdim // Needed for header files being rewritten 145243791Sdim bool IsHeader; 146243791Sdim bool SilenceRewriteMacroWarning; 147243791Sdim bool objc_impl_method; 148243791Sdim 149243791Sdim bool DisableReplaceStmt; 150243791Sdim class DisableReplaceStmtScope { 151243791Sdim RewriteObjC &R; 152243791Sdim bool SavedValue; 153243791Sdim 154243791Sdim public: 155243791Sdim DisableReplaceStmtScope(RewriteObjC &R) 156243791Sdim : R(R), SavedValue(R.DisableReplaceStmt) { 157243791Sdim R.DisableReplaceStmt = true; 158243791Sdim } 159243791Sdim ~DisableReplaceStmtScope() { 160243791Sdim R.DisableReplaceStmt = SavedValue; 161243791Sdim } 162243791Sdim }; 163243791Sdim void InitializeCommon(ASTContext &context); 164243791Sdim 165243791Sdim public: 166243791Sdim 167243791Sdim // Top Level Driver code. 168243791Sdim virtual bool HandleTopLevelDecl(DeclGroupRef D) { 169243791Sdim for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 170243791Sdim if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) { 171243791Sdim if (!Class->isThisDeclarationADefinition()) { 172243791Sdim RewriteForwardClassDecl(D); 173243791Sdim break; 174243791Sdim } 175243791Sdim } 176243791Sdim 177243791Sdim if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) { 178243791Sdim if (!Proto->isThisDeclarationADefinition()) { 179243791Sdim RewriteForwardProtocolDecl(D); 180243791Sdim break; 181243791Sdim } 182243791Sdim } 183243791Sdim 184243791Sdim HandleTopLevelSingleDecl(*I); 185243791Sdim } 186243791Sdim return true; 187243791Sdim } 188243791Sdim void HandleTopLevelSingleDecl(Decl *D); 189243791Sdim void HandleDeclInMainFile(Decl *D); 190243791Sdim RewriteObjC(std::string inFile, raw_ostream *OS, 191243791Sdim DiagnosticsEngine &D, const LangOptions &LOpts, 192243791Sdim bool silenceMacroWarn); 193243791Sdim 194243791Sdim ~RewriteObjC() {} 195243791Sdim 196243791Sdim virtual void HandleTranslationUnit(ASTContext &C); 197243791Sdim 198243791Sdim void ReplaceStmt(Stmt *Old, Stmt *New) { 199243791Sdim Stmt *ReplacingStmt = ReplacedNodes[Old]; 200243791Sdim 201243791Sdim if (ReplacingStmt) 202243791Sdim return; // We can't rewrite the same node twice. 203243791Sdim 204243791Sdim if (DisableReplaceStmt) 205243791Sdim return; 206243791Sdim 207243791Sdim // If replacement succeeded or warning disabled return with no warning. 208243791Sdim if (!Rewrite.ReplaceStmt(Old, New)) { 209243791Sdim ReplacedNodes[Old] = New; 210243791Sdim return; 211243791Sdim } 212243791Sdim if (SilenceRewriteMacroWarning) 213243791Sdim return; 214243791Sdim Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 215243791Sdim << Old->getSourceRange(); 216243791Sdim } 217243791Sdim 218243791Sdim void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { 219243791Sdim if (DisableReplaceStmt) 220243791Sdim return; 221243791Sdim 222243791Sdim // Measure the old text. 223243791Sdim int Size = Rewrite.getRangeSize(SrcRange); 224243791Sdim if (Size == -1) { 225243791Sdim Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 226243791Sdim << Old->getSourceRange(); 227243791Sdim return; 228243791Sdim } 229243791Sdim // Get the new text. 230243791Sdim std::string SStr; 231243791Sdim llvm::raw_string_ostream S(SStr); 232243791Sdim New->printPretty(S, 0, PrintingPolicy(LangOpts)); 233243791Sdim const std::string &Str = S.str(); 234243791Sdim 235243791Sdim // If replacement succeeded or warning disabled return with no warning. 236243791Sdim if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) { 237243791Sdim ReplacedNodes[Old] = New; 238243791Sdim return; 239243791Sdim } 240243791Sdim if (SilenceRewriteMacroWarning) 241243791Sdim return; 242243791Sdim Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 243243791Sdim << Old->getSourceRange(); 244243791Sdim } 245243791Sdim 246243791Sdim void InsertText(SourceLocation Loc, StringRef Str, 247243791Sdim bool InsertAfter = true) { 248243791Sdim // If insertion succeeded or warning disabled return with no warning. 249243791Sdim if (!Rewrite.InsertText(Loc, Str, InsertAfter) || 250243791Sdim SilenceRewriteMacroWarning) 251243791Sdim return; 252243791Sdim 253243791Sdim Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 254243791Sdim } 255243791Sdim 256243791Sdim void ReplaceText(SourceLocation Start, unsigned OrigLength, 257243791Sdim StringRef Str) { 258243791Sdim // If removal succeeded or warning disabled return with no warning. 259243791Sdim if (!Rewrite.ReplaceText(Start, OrigLength, Str) || 260243791Sdim SilenceRewriteMacroWarning) 261243791Sdim return; 262243791Sdim 263243791Sdim Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); 264243791Sdim } 265243791Sdim 266243791Sdim // Syntactic Rewriting. 267243791Sdim void RewriteRecordBody(RecordDecl *RD); 268243791Sdim void RewriteInclude(); 269243791Sdim void RewriteForwardClassDecl(DeclGroupRef D); 270263508Sdim void RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &DG); 271243791Sdim void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 272243791Sdim const std::string &typedefString); 273243791Sdim void RewriteImplementations(); 274243791Sdim void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 275243791Sdim ObjCImplementationDecl *IMD, 276243791Sdim ObjCCategoryImplDecl *CID); 277243791Sdim void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); 278243791Sdim void RewriteImplementationDecl(Decl *Dcl); 279243791Sdim void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 280243791Sdim ObjCMethodDecl *MDecl, std::string &ResultStr); 281243791Sdim void RewriteTypeIntoString(QualType T, std::string &ResultStr, 282243791Sdim const FunctionType *&FPRetType); 283243791Sdim void RewriteByRefString(std::string &ResultStr, const std::string &Name, 284243791Sdim ValueDecl *VD, bool def=false); 285243791Sdim void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); 286243791Sdim void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); 287243791Sdim void RewriteForwardProtocolDecl(DeclGroupRef D); 288263508Sdim void RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG); 289243791Sdim void RewriteMethodDeclaration(ObjCMethodDecl *Method); 290243791Sdim void RewriteProperty(ObjCPropertyDecl *prop); 291243791Sdim void RewriteFunctionDecl(FunctionDecl *FD); 292243791Sdim void RewriteBlockPointerType(std::string& Str, QualType Type); 293243791Sdim void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD); 294243791Sdim void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); 295243791Sdim void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); 296243791Sdim void RewriteTypeOfDecl(VarDecl *VD); 297243791Sdim void RewriteObjCQualifiedInterfaceTypes(Expr *E); 298243791Sdim 299243791Sdim // Expression Rewriting. 300243791Sdim Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); 301243791Sdim Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); 302243791Sdim Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo); 303243791Sdim Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo); 304243791Sdim Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); 305243791Sdim Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); 306243791Sdim Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); 307243791Sdim Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); 308243791Sdim void RewriteTryReturnStmts(Stmt *S); 309243791Sdim void RewriteSyncReturnStmts(Stmt *S, std::string buf); 310243791Sdim Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); 311243791Sdim Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); 312243791Sdim Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); 313243791Sdim Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 314243791Sdim SourceLocation OrigEnd); 315243791Sdim Stmt *RewriteBreakStmt(BreakStmt *S); 316243791Sdim Stmt *RewriteContinueStmt(ContinueStmt *S); 317243791Sdim void RewriteCastExpr(CStyleCastExpr *CE); 318243791Sdim 319243791Sdim // Block rewriting. 320243791Sdim void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); 321243791Sdim 322243791Sdim // Block specific rewrite rules. 323243791Sdim void RewriteBlockPointerDecl(NamedDecl *VD); 324243791Sdim void RewriteByRefVar(VarDecl *VD); 325243791Sdim Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD); 326243791Sdim Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); 327243791Sdim void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); 328243791Sdim 329243791Sdim void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 330243791Sdim std::string &Result); 331243791Sdim 332243791Sdim virtual void Initialize(ASTContext &context) = 0; 333243791Sdim 334243791Sdim // Metadata Rewriting. 335243791Sdim virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0; 336243791Sdim virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, 337243791Sdim StringRef prefix, 338243791Sdim StringRef ClassName, 339243791Sdim std::string &Result) = 0; 340243791Sdim virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 341243791Sdim std::string &Result) = 0; 342243791Sdim virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 343243791Sdim StringRef prefix, 344243791Sdim StringRef ClassName, 345243791Sdim std::string &Result) = 0; 346243791Sdim virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 347243791Sdim std::string &Result) = 0; 348243791Sdim 349243791Sdim // Rewriting ivar access 350243791Sdim virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0; 351243791Sdim virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 352243791Sdim std::string &Result) = 0; 353243791Sdim 354243791Sdim // Misc. AST transformation routines. Sometimes they end up calling 355243791Sdim // rewriting routines on the new ASTs. 356243791Sdim CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 357243791Sdim Expr **args, unsigned nargs, 358243791Sdim SourceLocation StartLoc=SourceLocation(), 359243791Sdim SourceLocation EndLoc=SourceLocation()); 360243791Sdim CallExpr *SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, 361243791Sdim QualType msgSendType, 362243791Sdim QualType returnType, 363243791Sdim SmallVectorImpl<QualType> &ArgTypes, 364243791Sdim SmallVectorImpl<Expr*> &MsgExprs, 365243791Sdim ObjCMethodDecl *Method); 366243791Sdim Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, 367243791Sdim SourceLocation StartLoc=SourceLocation(), 368243791Sdim SourceLocation EndLoc=SourceLocation()); 369243791Sdim 370243791Sdim void SynthCountByEnumWithState(std::string &buf); 371243791Sdim void SynthMsgSendFunctionDecl(); 372243791Sdim void SynthMsgSendSuperFunctionDecl(); 373243791Sdim void SynthMsgSendStretFunctionDecl(); 374243791Sdim void SynthMsgSendFpretFunctionDecl(); 375243791Sdim void SynthMsgSendSuperStretFunctionDecl(); 376243791Sdim void SynthGetClassFunctionDecl(); 377243791Sdim void SynthGetMetaClassFunctionDecl(); 378243791Sdim void SynthGetSuperClassFunctionDecl(); 379243791Sdim void SynthSelGetUidFunctionDecl(); 380263508Sdim void SynthSuperConstructorFunctionDecl(); 381243791Sdim 382243791Sdim std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); 383243791Sdim std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 384243791Sdim StringRef funcName, std::string Tag); 385243791Sdim std::string SynthesizeBlockFunc(BlockExpr *CE, int i, 386243791Sdim StringRef funcName, std::string Tag); 387243791Sdim std::string SynthesizeBlockImpl(BlockExpr *CE, 388243791Sdim std::string Tag, std::string Desc); 389243791Sdim std::string SynthesizeBlockDescriptor(std::string DescTag, 390243791Sdim std::string ImplTag, 391243791Sdim int i, StringRef funcName, 392243791Sdim unsigned hasCopy); 393243791Sdim Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); 394243791Sdim void SynthesizeBlockLiterals(SourceLocation FunLocStart, 395243791Sdim StringRef FunName); 396243791Sdim FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); 397243791Sdim Stmt *SynthBlockInitExpr(BlockExpr *Exp, 398263508Sdim const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs); 399243791Sdim 400243791Sdim // Misc. helper routines. 401243791Sdim QualType getProtocolType(); 402243791Sdim void WarnAboutReturnGotoStmts(Stmt *S); 403243791Sdim void HasReturnStmts(Stmt *S, bool &hasReturns); 404243791Sdim void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); 405243791Sdim void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); 406243791Sdim void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); 407243791Sdim 408243791Sdim bool IsDeclStmtInForeachHeader(DeclStmt *DS); 409243791Sdim void CollectBlockDeclRefInfo(BlockExpr *Exp); 410243791Sdim void GetBlockDeclRefExprs(Stmt *S); 411263508Sdim void GetInnerBlockDeclRefExprs(Stmt *S, 412263508Sdim SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs, 413243791Sdim llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts); 414243791Sdim 415243791Sdim // We avoid calling Type::isBlockPointerType(), since it operates on the 416243791Sdim // canonical type. We only care if the top-level type is a closure pointer. 417243791Sdim bool isTopLevelBlockPointerType(QualType T) { 418243791Sdim return isa<BlockPointerType>(T); 419243791Sdim } 420243791Sdim 421243791Sdim /// convertBlockPointerToFunctionPointer - Converts a block-pointer type 422243791Sdim /// to a function pointer type and upon success, returns true; false 423243791Sdim /// otherwise. 424243791Sdim bool convertBlockPointerToFunctionPointer(QualType &T) { 425243791Sdim if (isTopLevelBlockPointerType(T)) { 426243791Sdim const BlockPointerType *BPT = T->getAs<BlockPointerType>(); 427243791Sdim T = Context->getPointerType(BPT->getPointeeType()); 428243791Sdim return true; 429243791Sdim } 430243791Sdim return false; 431243791Sdim } 432243791Sdim 433243791Sdim bool needToScanForQualifiers(QualType T); 434243791Sdim QualType getSuperStructType(); 435243791Sdim QualType getConstantStringStructType(); 436243791Sdim QualType convertFunctionTypeOfBlocks(const FunctionType *FT); 437243791Sdim bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); 438243791Sdim 439243791Sdim void convertToUnqualifiedObjCType(QualType &T) { 440243791Sdim if (T->isObjCQualifiedIdType()) 441243791Sdim T = Context->getObjCIdType(); 442243791Sdim else if (T->isObjCQualifiedClassType()) 443243791Sdim T = Context->getObjCClassType(); 444243791Sdim else if (T->isObjCObjectPointerType() && 445243791Sdim T->getPointeeType()->isObjCQualifiedInterfaceType()) { 446243791Sdim if (const ObjCObjectPointerType * OBJPT = 447243791Sdim T->getAsObjCInterfacePointerType()) { 448243791Sdim const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); 449243791Sdim T = QualType(IFaceT, 0); 450243791Sdim T = Context->getPointerType(T); 451243791Sdim } 452243791Sdim } 453243791Sdim } 454243791Sdim 455243791Sdim // FIXME: This predicate seems like it would be useful to add to ASTContext. 456243791Sdim bool isObjCType(QualType T) { 457243791Sdim if (!LangOpts.ObjC1 && !LangOpts.ObjC2) 458243791Sdim return false; 459243791Sdim 460243791Sdim QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); 461243791Sdim 462243791Sdim if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || 463243791Sdim OCT == Context->getCanonicalType(Context->getObjCClassType())) 464243791Sdim return true; 465243791Sdim 466243791Sdim if (const PointerType *PT = OCT->getAs<PointerType>()) { 467243791Sdim if (isa<ObjCInterfaceType>(PT->getPointeeType()) || 468243791Sdim PT->getPointeeType()->isObjCQualifiedIdType()) 469243791Sdim return true; 470243791Sdim } 471243791Sdim return false; 472243791Sdim } 473243791Sdim bool PointerTypeTakesAnyBlockArguments(QualType QT); 474243791Sdim bool PointerTypeTakesAnyObjCQualifiedType(QualType QT); 475243791Sdim void GetExtentOfArgList(const char *Name, const char *&LParen, 476243791Sdim const char *&RParen); 477243791Sdim 478243791Sdim void QuoteDoublequotes(std::string &From, std::string &To) { 479243791Sdim for (unsigned i = 0; i < From.length(); i++) { 480243791Sdim if (From[i] == '"') 481243791Sdim To += "\\\""; 482243791Sdim else 483243791Sdim To += From[i]; 484243791Sdim } 485243791Sdim } 486243791Sdim 487243791Sdim QualType getSimpleFunctionType(QualType result, 488249423Sdim ArrayRef<QualType> args, 489243791Sdim bool variadic = false) { 490243791Sdim if (result == Context->getObjCInstanceType()) 491243791Sdim result = Context->getObjCIdType(); 492243791Sdim FunctionProtoType::ExtProtoInfo fpi; 493243791Sdim fpi.Variadic = variadic; 494249423Sdim return Context->getFunctionType(result, args, fpi); 495243791Sdim } 496243791Sdim 497243791Sdim // Helper function: create a CStyleCastExpr with trivial type source info. 498243791Sdim CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, 499243791Sdim CastKind Kind, Expr *E) { 500243791Sdim TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); 501243791Sdim return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo, 502243791Sdim SourceLocation(), SourceLocation()); 503243791Sdim } 504243791Sdim }; 505243791Sdim 506243791Sdim class RewriteObjCFragileABI : public RewriteObjC { 507243791Sdim public: 508243791Sdim 509243791Sdim RewriteObjCFragileABI(std::string inFile, raw_ostream *OS, 510243791Sdim DiagnosticsEngine &D, const LangOptions &LOpts, 511243791Sdim bool silenceMacroWarn) : RewriteObjC(inFile, OS, 512243791Sdim D, LOpts, 513243791Sdim silenceMacroWarn) {} 514243791Sdim 515243791Sdim ~RewriteObjCFragileABI() {} 516243791Sdim virtual void Initialize(ASTContext &context); 517243791Sdim 518243791Sdim // Rewriting metadata 519243791Sdim template<typename MethodIterator> 520243791Sdim void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 521243791Sdim MethodIterator MethodEnd, 522243791Sdim bool IsInstanceMethod, 523243791Sdim StringRef prefix, 524243791Sdim StringRef ClassName, 525243791Sdim std::string &Result); 526243791Sdim virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 527243791Sdim StringRef prefix, 528243791Sdim StringRef ClassName, 529243791Sdim std::string &Result); 530243791Sdim virtual void RewriteObjCProtocolListMetaData( 531243791Sdim const ObjCList<ObjCProtocolDecl> &Prots, 532243791Sdim StringRef prefix, StringRef ClassName, std::string &Result); 533243791Sdim virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 534243791Sdim std::string &Result); 535243791Sdim virtual void RewriteMetaDataIntoBuffer(std::string &Result); 536243791Sdim virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 537243791Sdim std::string &Result); 538243791Sdim 539243791Sdim // Rewriting ivar 540243791Sdim virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 541243791Sdim std::string &Result); 542243791Sdim virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV); 543243791Sdim }; 544243791Sdim} 545243791Sdim 546243791Sdimvoid RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, 547243791Sdim NamedDecl *D) { 548243791Sdim if (const FunctionProtoType *fproto 549243791Sdim = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) { 550243791Sdim for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), 551243791Sdim E = fproto->arg_type_end(); I && (I != E); ++I) 552243791Sdim if (isTopLevelBlockPointerType(*I)) { 553243791Sdim // All the args are checked/rewritten. Don't call twice! 554243791Sdim RewriteBlockPointerDecl(D); 555243791Sdim break; 556243791Sdim } 557243791Sdim } 558243791Sdim} 559243791Sdim 560243791Sdimvoid RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { 561243791Sdim const PointerType *PT = funcType->getAs<PointerType>(); 562243791Sdim if (PT && PointerTypeTakesAnyBlockArguments(funcType)) 563243791Sdim RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); 564243791Sdim} 565243791Sdim 566243791Sdimstatic bool IsHeaderFile(const std::string &Filename) { 567243791Sdim std::string::size_type DotPos = Filename.rfind('.'); 568243791Sdim 569243791Sdim if (DotPos == std::string::npos) { 570243791Sdim // no file extension 571243791Sdim return false; 572243791Sdim } 573243791Sdim 574243791Sdim std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); 575243791Sdim // C header: .h 576243791Sdim // C++ header: .hh or .H; 577243791Sdim return Ext == "h" || Ext == "hh" || Ext == "H"; 578243791Sdim} 579243791Sdim 580243791SdimRewriteObjC::RewriteObjC(std::string inFile, raw_ostream* OS, 581243791Sdim DiagnosticsEngine &D, const LangOptions &LOpts, 582243791Sdim bool silenceMacroWarn) 583243791Sdim : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS), 584243791Sdim SilenceRewriteMacroWarning(silenceMacroWarn) { 585243791Sdim IsHeader = IsHeaderFile(inFile); 586243791Sdim RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 587243791Sdim "rewriting sub-expression within a macro (may not be correct)"); 588243791Sdim TryFinallyContainsReturnDiag = Diags.getCustomDiagID( 589243791Sdim DiagnosticsEngine::Warning, 590243791Sdim "rewriter doesn't support user-specified control flow semantics " 591243791Sdim "for @try/@finally (code may not execute properly)"); 592243791Sdim} 593243791Sdim 594243791SdimASTConsumer *clang::CreateObjCRewriter(const std::string& InFile, 595243791Sdim raw_ostream* OS, 596243791Sdim DiagnosticsEngine &Diags, 597243791Sdim const LangOptions &LOpts, 598243791Sdim bool SilenceRewriteMacroWarning) { 599243791Sdim return new RewriteObjCFragileABI(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); 600243791Sdim} 601243791Sdim 602243791Sdimvoid RewriteObjC::InitializeCommon(ASTContext &context) { 603243791Sdim Context = &context; 604243791Sdim SM = &Context->getSourceManager(); 605243791Sdim TUDecl = Context->getTranslationUnitDecl(); 606243791Sdim MsgSendFunctionDecl = 0; 607243791Sdim MsgSendSuperFunctionDecl = 0; 608243791Sdim MsgSendStretFunctionDecl = 0; 609243791Sdim MsgSendSuperStretFunctionDecl = 0; 610243791Sdim MsgSendFpretFunctionDecl = 0; 611243791Sdim GetClassFunctionDecl = 0; 612243791Sdim GetMetaClassFunctionDecl = 0; 613243791Sdim GetSuperClassFunctionDecl = 0; 614243791Sdim SelGetUidFunctionDecl = 0; 615243791Sdim CFStringFunctionDecl = 0; 616243791Sdim ConstantStringClassReference = 0; 617243791Sdim NSStringRecord = 0; 618243791Sdim CurMethodDef = 0; 619243791Sdim CurFunctionDef = 0; 620243791Sdim CurFunctionDeclToDeclareForBlock = 0; 621243791Sdim GlobalVarDecl = 0; 622243791Sdim SuperStructDecl = 0; 623243791Sdim ProtocolTypeDecl = 0; 624243791Sdim ConstantStringDecl = 0; 625243791Sdim BcLabelCount = 0; 626263508Sdim SuperConstructorFunctionDecl = 0; 627243791Sdim NumObjCStringLiterals = 0; 628243791Sdim PropParentMap = 0; 629243791Sdim CurrentBody = 0; 630243791Sdim DisableReplaceStmt = false; 631243791Sdim objc_impl_method = false; 632243791Sdim 633243791Sdim // Get the ID and start/end of the main file. 634243791Sdim MainFileID = SM->getMainFileID(); 635243791Sdim const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID); 636243791Sdim MainFileStart = MainBuf->getBufferStart(); 637243791Sdim MainFileEnd = MainBuf->getBufferEnd(); 638243791Sdim 639243791Sdim Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts()); 640243791Sdim} 641243791Sdim 642243791Sdim//===----------------------------------------------------------------------===// 643243791Sdim// Top Level Driver Code 644243791Sdim//===----------------------------------------------------------------------===// 645243791Sdim 646243791Sdimvoid RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { 647243791Sdim if (Diags.hasErrorOccurred()) 648243791Sdim return; 649243791Sdim 650243791Sdim // Two cases: either the decl could be in the main file, or it could be in a 651243791Sdim // #included file. If the former, rewrite it now. If the later, check to see 652243791Sdim // if we rewrote the #include/#import. 653243791Sdim SourceLocation Loc = D->getLocation(); 654243791Sdim Loc = SM->getExpansionLoc(Loc); 655243791Sdim 656243791Sdim // If this is for a builtin, ignore it. 657243791Sdim if (Loc.isInvalid()) return; 658243791Sdim 659243791Sdim // Look for built-in declarations that we need to refer during the rewrite. 660243791Sdim if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 661243791Sdim RewriteFunctionDecl(FD); 662243791Sdim } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) { 663243791Sdim // declared in <Foundation/NSString.h> 664243791Sdim if (FVD->getName() == "_NSConstantStringClassReference") { 665243791Sdim ConstantStringClassReference = FVD; 666243791Sdim return; 667243791Sdim } 668243791Sdim } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { 669243791Sdim if (ID->isThisDeclarationADefinition()) 670243791Sdim RewriteInterfaceDecl(ID); 671243791Sdim } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { 672243791Sdim RewriteCategoryDecl(CD); 673243791Sdim } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { 674243791Sdim if (PD->isThisDeclarationADefinition()) 675243791Sdim RewriteProtocolDecl(PD); 676243791Sdim } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { 677243791Sdim // Recurse into linkage specifications 678243791Sdim for (DeclContext::decl_iterator DI = LSD->decls_begin(), 679243791Sdim DIEnd = LSD->decls_end(); 680243791Sdim DI != DIEnd; ) { 681243791Sdim if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) { 682243791Sdim if (!IFace->isThisDeclarationADefinition()) { 683243791Sdim SmallVector<Decl *, 8> DG; 684243791Sdim SourceLocation StartLoc = IFace->getLocStart(); 685243791Sdim do { 686243791Sdim if (isa<ObjCInterfaceDecl>(*DI) && 687243791Sdim !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() && 688243791Sdim StartLoc == (*DI)->getLocStart()) 689243791Sdim DG.push_back(*DI); 690243791Sdim else 691243791Sdim break; 692243791Sdim 693243791Sdim ++DI; 694243791Sdim } while (DI != DIEnd); 695243791Sdim RewriteForwardClassDecl(DG); 696243791Sdim continue; 697243791Sdim } 698243791Sdim } 699243791Sdim 700243791Sdim if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) { 701243791Sdim if (!Proto->isThisDeclarationADefinition()) { 702243791Sdim SmallVector<Decl *, 8> DG; 703243791Sdim SourceLocation StartLoc = Proto->getLocStart(); 704243791Sdim do { 705243791Sdim if (isa<ObjCProtocolDecl>(*DI) && 706243791Sdim !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() && 707243791Sdim StartLoc == (*DI)->getLocStart()) 708243791Sdim DG.push_back(*DI); 709243791Sdim else 710243791Sdim break; 711243791Sdim 712243791Sdim ++DI; 713243791Sdim } while (DI != DIEnd); 714243791Sdim RewriteForwardProtocolDecl(DG); 715243791Sdim continue; 716243791Sdim } 717243791Sdim } 718243791Sdim 719243791Sdim HandleTopLevelSingleDecl(*DI); 720243791Sdim ++DI; 721243791Sdim } 722243791Sdim } 723243791Sdim // If we have a decl in the main file, see if we should rewrite it. 724263508Sdim if (SM->isWrittenInMainFile(Loc)) 725243791Sdim return HandleDeclInMainFile(D); 726243791Sdim} 727243791Sdim 728243791Sdim//===----------------------------------------------------------------------===// 729243791Sdim// Syntactic (non-AST) Rewriting Code 730243791Sdim//===----------------------------------------------------------------------===// 731243791Sdim 732243791Sdimvoid RewriteObjC::RewriteInclude() { 733243791Sdim SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); 734243791Sdim StringRef MainBuf = SM->getBufferData(MainFileID); 735243791Sdim const char *MainBufStart = MainBuf.begin(); 736243791Sdim const char *MainBufEnd = MainBuf.end(); 737243791Sdim size_t ImportLen = strlen("import"); 738243791Sdim 739243791Sdim // Loop over the whole file, looking for includes. 740243791Sdim for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { 741243791Sdim if (*BufPtr == '#') { 742243791Sdim if (++BufPtr == MainBufEnd) 743243791Sdim return; 744243791Sdim while (*BufPtr == ' ' || *BufPtr == '\t') 745243791Sdim if (++BufPtr == MainBufEnd) 746243791Sdim return; 747243791Sdim if (!strncmp(BufPtr, "import", ImportLen)) { 748243791Sdim // replace import with include 749243791Sdim SourceLocation ImportLoc = 750243791Sdim LocStart.getLocWithOffset(BufPtr-MainBufStart); 751243791Sdim ReplaceText(ImportLoc, ImportLen, "include"); 752243791Sdim BufPtr += ImportLen; 753243791Sdim } 754243791Sdim } 755243791Sdim } 756243791Sdim} 757243791Sdim 758243791Sdimstatic std::string getIvarAccessString(ObjCIvarDecl *OID) { 759243791Sdim const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface(); 760243791Sdim std::string S; 761243791Sdim S = "((struct "; 762243791Sdim S += ClassDecl->getIdentifier()->getName(); 763243791Sdim S += "_IMPL *)self)->"; 764243791Sdim S += OID->getName(); 765243791Sdim return S; 766243791Sdim} 767243791Sdim 768243791Sdimvoid RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 769243791Sdim ObjCImplementationDecl *IMD, 770243791Sdim ObjCCategoryImplDecl *CID) { 771243791Sdim static bool objcGetPropertyDefined = false; 772243791Sdim static bool objcSetPropertyDefined = false; 773243791Sdim SourceLocation startLoc = PID->getLocStart(); 774243791Sdim InsertText(startLoc, "// "); 775243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 776243791Sdim assert((*startBuf == '@') && "bogus @synthesize location"); 777243791Sdim const char *semiBuf = strchr(startBuf, ';'); 778243791Sdim assert((*semiBuf == ';') && "@synthesize: can't find ';'"); 779243791Sdim SourceLocation onePastSemiLoc = 780243791Sdim startLoc.getLocWithOffset(semiBuf-startBuf+1); 781243791Sdim 782243791Sdim if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 783243791Sdim return; // FIXME: is this correct? 784243791Sdim 785243791Sdim // Generate the 'getter' function. 786243791Sdim ObjCPropertyDecl *PD = PID->getPropertyDecl(); 787243791Sdim ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); 788243791Sdim 789243791Sdim if (!OID) 790243791Sdim return; 791243791Sdim unsigned Attributes = PD->getPropertyAttributes(); 792243791Sdim if (!PD->getGetterMethodDecl()->isDefined()) { 793243791Sdim bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) && 794243791Sdim (Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 795243791Sdim ObjCPropertyDecl::OBJC_PR_copy)); 796243791Sdim std::string Getr; 797243791Sdim if (GenGetProperty && !objcGetPropertyDefined) { 798243791Sdim objcGetPropertyDefined = true; 799243791Sdim // FIXME. Is this attribute correct in all cases? 800243791Sdim Getr = "\nextern \"C\" __declspec(dllimport) " 801243791Sdim "id objc_getProperty(id, SEL, long, bool);\n"; 802243791Sdim } 803243791Sdim RewriteObjCMethodDecl(OID->getContainingInterface(), 804243791Sdim PD->getGetterMethodDecl(), Getr); 805243791Sdim Getr += "{ "; 806243791Sdim // Synthesize an explicit cast to gain access to the ivar. 807243791Sdim // See objc-act.c:objc_synthesize_new_getter() for details. 808243791Sdim if (GenGetProperty) { 809243791Sdim // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) 810243791Sdim Getr += "typedef "; 811243791Sdim const FunctionType *FPRetType = 0; 812243791Sdim RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr, 813243791Sdim FPRetType); 814243791Sdim Getr += " _TYPE"; 815243791Sdim if (FPRetType) { 816243791Sdim Getr += ")"; // close the precedence "scope" for "*". 817243791Sdim 818243791Sdim // Now, emit the argument types (if any). 819243791Sdim if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){ 820243791Sdim Getr += "("; 821243791Sdim for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 822243791Sdim if (i) Getr += ", "; 823243791Sdim std::string ParamStr = FT->getArgType(i).getAsString( 824243791Sdim Context->getPrintingPolicy()); 825243791Sdim Getr += ParamStr; 826243791Sdim } 827243791Sdim if (FT->isVariadic()) { 828243791Sdim if (FT->getNumArgs()) Getr += ", "; 829243791Sdim Getr += "..."; 830243791Sdim } 831243791Sdim Getr += ")"; 832243791Sdim } else 833243791Sdim Getr += "()"; 834243791Sdim } 835243791Sdim Getr += ";\n"; 836243791Sdim Getr += "return (_TYPE)"; 837243791Sdim Getr += "objc_getProperty(self, _cmd, "; 838243791Sdim RewriteIvarOffsetComputation(OID, Getr); 839243791Sdim Getr += ", 1)"; 840243791Sdim } 841243791Sdim else 842243791Sdim Getr += "return " + getIvarAccessString(OID); 843243791Sdim Getr += "; }"; 844243791Sdim InsertText(onePastSemiLoc, Getr); 845243791Sdim } 846243791Sdim 847243791Sdim if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined()) 848243791Sdim return; 849243791Sdim 850243791Sdim // Generate the 'setter' function. 851243791Sdim std::string Setr; 852243791Sdim bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 853243791Sdim ObjCPropertyDecl::OBJC_PR_copy); 854243791Sdim if (GenSetProperty && !objcSetPropertyDefined) { 855243791Sdim objcSetPropertyDefined = true; 856243791Sdim // FIXME. Is this attribute correct in all cases? 857243791Sdim Setr = "\nextern \"C\" __declspec(dllimport) " 858243791Sdim "void objc_setProperty (id, SEL, long, id, bool, bool);\n"; 859243791Sdim } 860243791Sdim 861243791Sdim RewriteObjCMethodDecl(OID->getContainingInterface(), 862243791Sdim PD->getSetterMethodDecl(), Setr); 863243791Sdim Setr += "{ "; 864243791Sdim // Synthesize an explicit cast to initialize the ivar. 865243791Sdim // See objc-act.c:objc_synthesize_new_setter() for details. 866243791Sdim if (GenSetProperty) { 867243791Sdim Setr += "objc_setProperty (self, _cmd, "; 868243791Sdim RewriteIvarOffsetComputation(OID, Setr); 869243791Sdim Setr += ", (id)"; 870243791Sdim Setr += PD->getName(); 871243791Sdim Setr += ", "; 872243791Sdim if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) 873243791Sdim Setr += "0, "; 874243791Sdim else 875243791Sdim Setr += "1, "; 876243791Sdim if (Attributes & ObjCPropertyDecl::OBJC_PR_copy) 877243791Sdim Setr += "1)"; 878243791Sdim else 879243791Sdim Setr += "0)"; 880243791Sdim } 881243791Sdim else { 882243791Sdim Setr += getIvarAccessString(OID) + " = "; 883243791Sdim Setr += PD->getName(); 884243791Sdim } 885243791Sdim Setr += "; }"; 886243791Sdim InsertText(onePastSemiLoc, Setr); 887243791Sdim} 888243791Sdim 889243791Sdimstatic void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, 890243791Sdim std::string &typedefString) { 891243791Sdim typedefString += "#ifndef _REWRITER_typedef_"; 892243791Sdim typedefString += ForwardDecl->getNameAsString(); 893243791Sdim typedefString += "\n"; 894243791Sdim typedefString += "#define _REWRITER_typedef_"; 895243791Sdim typedefString += ForwardDecl->getNameAsString(); 896243791Sdim typedefString += "\n"; 897243791Sdim typedefString += "typedef struct objc_object "; 898243791Sdim typedefString += ForwardDecl->getNameAsString(); 899243791Sdim typedefString += ";\n#endif\n"; 900243791Sdim} 901243791Sdim 902243791Sdimvoid RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 903243791Sdim const std::string &typedefString) { 904243791Sdim SourceLocation startLoc = ClassDecl->getLocStart(); 905243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 906243791Sdim const char *semiPtr = strchr(startBuf, ';'); 907243791Sdim // Replace the @class with typedefs corresponding to the classes. 908243791Sdim ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); 909243791Sdim} 910243791Sdim 911243791Sdimvoid RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) { 912243791Sdim std::string typedefString; 913243791Sdim for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 914243791Sdim ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I); 915243791Sdim if (I == D.begin()) { 916243791Sdim // Translate to typedef's that forward reference structs with the same name 917243791Sdim // as the class. As a convenience, we include the original declaration 918243791Sdim // as a comment. 919243791Sdim typedefString += "// @class "; 920243791Sdim typedefString += ForwardDecl->getNameAsString(); 921243791Sdim typedefString += ";\n"; 922243791Sdim } 923243791Sdim RewriteOneForwardClassDecl(ForwardDecl, typedefString); 924243791Sdim } 925243791Sdim DeclGroupRef::iterator I = D.begin(); 926243791Sdim RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString); 927243791Sdim} 928243791Sdim 929263508Sdimvoid RewriteObjC::RewriteForwardClassDecl(const SmallVectorImpl<Decl *> &D) { 930243791Sdim std::string typedefString; 931243791Sdim for (unsigned i = 0; i < D.size(); i++) { 932243791Sdim ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]); 933243791Sdim if (i == 0) { 934243791Sdim typedefString += "// @class "; 935243791Sdim typedefString += ForwardDecl->getNameAsString(); 936243791Sdim typedefString += ";\n"; 937243791Sdim } 938243791Sdim RewriteOneForwardClassDecl(ForwardDecl, typedefString); 939243791Sdim } 940243791Sdim RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString); 941243791Sdim} 942243791Sdim 943243791Sdimvoid RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { 944243791Sdim // When method is a synthesized one, such as a getter/setter there is 945243791Sdim // nothing to rewrite. 946243791Sdim if (Method->isImplicit()) 947243791Sdim return; 948243791Sdim SourceLocation LocStart = Method->getLocStart(); 949243791Sdim SourceLocation LocEnd = Method->getLocEnd(); 950243791Sdim 951243791Sdim if (SM->getExpansionLineNumber(LocEnd) > 952243791Sdim SM->getExpansionLineNumber(LocStart)) { 953243791Sdim InsertText(LocStart, "#if 0\n"); 954243791Sdim ReplaceText(LocEnd, 1, ";\n#endif\n"); 955243791Sdim } else { 956243791Sdim InsertText(LocStart, "// "); 957243791Sdim } 958243791Sdim} 959243791Sdim 960243791Sdimvoid RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) { 961243791Sdim SourceLocation Loc = prop->getAtLoc(); 962243791Sdim 963243791Sdim ReplaceText(Loc, 0, "// "); 964243791Sdim // FIXME: handle properties that are declared across multiple lines. 965243791Sdim} 966243791Sdim 967243791Sdimvoid RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { 968243791Sdim SourceLocation LocStart = CatDecl->getLocStart(); 969243791Sdim 970243791Sdim // FIXME: handle category headers that are declared across multiple lines. 971243791Sdim ReplaceText(LocStart, 0, "// "); 972243791Sdim 973243791Sdim for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), 974243791Sdim E = CatDecl->prop_end(); I != E; ++I) 975243791Sdim RewriteProperty(*I); 976243791Sdim 977243791Sdim for (ObjCCategoryDecl::instmeth_iterator 978243791Sdim I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); 979243791Sdim I != E; ++I) 980243791Sdim RewriteMethodDeclaration(*I); 981243791Sdim for (ObjCCategoryDecl::classmeth_iterator 982243791Sdim I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); 983243791Sdim I != E; ++I) 984243791Sdim RewriteMethodDeclaration(*I); 985243791Sdim 986243791Sdim // Lastly, comment out the @end. 987243791Sdim ReplaceText(CatDecl->getAtEndRange().getBegin(), 988243791Sdim strlen("@end"), "/* @end */"); 989243791Sdim} 990243791Sdim 991243791Sdimvoid RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { 992243791Sdim SourceLocation LocStart = PDecl->getLocStart(); 993243791Sdim assert(PDecl->isThisDeclarationADefinition()); 994243791Sdim 995243791Sdim // FIXME: handle protocol headers that are declared across multiple lines. 996243791Sdim ReplaceText(LocStart, 0, "// "); 997243791Sdim 998243791Sdim for (ObjCProtocolDecl::instmeth_iterator 999243791Sdim I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 1000243791Sdim I != E; ++I) 1001243791Sdim RewriteMethodDeclaration(*I); 1002243791Sdim for (ObjCProtocolDecl::classmeth_iterator 1003243791Sdim I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 1004243791Sdim I != E; ++I) 1005243791Sdim RewriteMethodDeclaration(*I); 1006243791Sdim 1007243791Sdim for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(), 1008243791Sdim E = PDecl->prop_end(); I != E; ++I) 1009243791Sdim RewriteProperty(*I); 1010243791Sdim 1011243791Sdim // Lastly, comment out the @end. 1012243791Sdim SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); 1013243791Sdim ReplaceText(LocEnd, strlen("@end"), "/* @end */"); 1014243791Sdim 1015243791Sdim // Must comment out @optional/@required 1016243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 1017243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 1018243791Sdim for (const char *p = startBuf; p < endBuf; p++) { 1019243791Sdim if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { 1020243791Sdim SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 1021243791Sdim ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); 1022243791Sdim 1023243791Sdim } 1024243791Sdim else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { 1025243791Sdim SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 1026243791Sdim ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); 1027243791Sdim 1028243791Sdim } 1029243791Sdim } 1030243791Sdim} 1031243791Sdim 1032243791Sdimvoid RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) { 1033243791Sdim SourceLocation LocStart = (*D.begin())->getLocStart(); 1034243791Sdim if (LocStart.isInvalid()) 1035243791Sdim llvm_unreachable("Invalid SourceLocation"); 1036243791Sdim // FIXME: handle forward protocol that are declared across multiple lines. 1037243791Sdim ReplaceText(LocStart, 0, "// "); 1038243791Sdim} 1039243791Sdim 1040243791Sdimvoid 1041263508SdimRewriteObjC::RewriteForwardProtocolDecl(const SmallVectorImpl<Decl *> &DG) { 1042243791Sdim SourceLocation LocStart = DG[0]->getLocStart(); 1043243791Sdim if (LocStart.isInvalid()) 1044243791Sdim llvm_unreachable("Invalid SourceLocation"); 1045243791Sdim // FIXME: handle forward protocol that are declared across multiple lines. 1046243791Sdim ReplaceText(LocStart, 0, "// "); 1047243791Sdim} 1048243791Sdim 1049243791Sdimvoid RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr, 1050243791Sdim const FunctionType *&FPRetType) { 1051243791Sdim if (T->isObjCQualifiedIdType()) 1052243791Sdim ResultStr += "id"; 1053243791Sdim else if (T->isFunctionPointerType() || 1054243791Sdim T->isBlockPointerType()) { 1055243791Sdim // needs special handling, since pointer-to-functions have special 1056243791Sdim // syntax (where a decaration models use). 1057243791Sdim QualType retType = T; 1058243791Sdim QualType PointeeTy; 1059243791Sdim if (const PointerType* PT = retType->getAs<PointerType>()) 1060243791Sdim PointeeTy = PT->getPointeeType(); 1061243791Sdim else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) 1062243791Sdim PointeeTy = BPT->getPointeeType(); 1063243791Sdim if ((FPRetType = PointeeTy->getAs<FunctionType>())) { 1064243791Sdim ResultStr += FPRetType->getResultType().getAsString( 1065243791Sdim Context->getPrintingPolicy()); 1066243791Sdim ResultStr += "(*"; 1067243791Sdim } 1068243791Sdim } else 1069243791Sdim ResultStr += T.getAsString(Context->getPrintingPolicy()); 1070243791Sdim} 1071243791Sdim 1072243791Sdimvoid RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 1073243791Sdim ObjCMethodDecl *OMD, 1074243791Sdim std::string &ResultStr) { 1075243791Sdim //fprintf(stderr,"In RewriteObjCMethodDecl\n"); 1076243791Sdim const FunctionType *FPRetType = 0; 1077243791Sdim ResultStr += "\nstatic "; 1078243791Sdim RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType); 1079243791Sdim ResultStr += " "; 1080243791Sdim 1081243791Sdim // Unique method name 1082243791Sdim std::string NameStr; 1083243791Sdim 1084243791Sdim if (OMD->isInstanceMethod()) 1085243791Sdim NameStr += "_I_"; 1086243791Sdim else 1087243791Sdim NameStr += "_C_"; 1088243791Sdim 1089243791Sdim NameStr += IDecl->getNameAsString(); 1090243791Sdim NameStr += "_"; 1091243791Sdim 1092243791Sdim if (ObjCCategoryImplDecl *CID = 1093243791Sdim dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 1094243791Sdim NameStr += CID->getNameAsString(); 1095243791Sdim NameStr += "_"; 1096243791Sdim } 1097243791Sdim // Append selector names, replacing ':' with '_' 1098243791Sdim { 1099243791Sdim std::string selString = OMD->getSelector().getAsString(); 1100243791Sdim int len = selString.size(); 1101243791Sdim for (int i = 0; i < len; i++) 1102243791Sdim if (selString[i] == ':') 1103243791Sdim selString[i] = '_'; 1104243791Sdim NameStr += selString; 1105243791Sdim } 1106243791Sdim // Remember this name for metadata emission 1107243791Sdim MethodInternalNames[OMD] = NameStr; 1108243791Sdim ResultStr += NameStr; 1109243791Sdim 1110243791Sdim // Rewrite arguments 1111243791Sdim ResultStr += "("; 1112243791Sdim 1113243791Sdim // invisible arguments 1114243791Sdim if (OMD->isInstanceMethod()) { 1115243791Sdim QualType selfTy = Context->getObjCInterfaceType(IDecl); 1116243791Sdim selfTy = Context->getPointerType(selfTy); 1117243791Sdim if (!LangOpts.MicrosoftExt) { 1118243791Sdim if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl))) 1119243791Sdim ResultStr += "struct "; 1120243791Sdim } 1121243791Sdim // When rewriting for Microsoft, explicitly omit the structure name. 1122243791Sdim ResultStr += IDecl->getNameAsString(); 1123243791Sdim ResultStr += " *"; 1124243791Sdim } 1125243791Sdim else 1126243791Sdim ResultStr += Context->getObjCClassType().getAsString( 1127243791Sdim Context->getPrintingPolicy()); 1128243791Sdim 1129243791Sdim ResultStr += " self, "; 1130243791Sdim ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy()); 1131243791Sdim ResultStr += " _cmd"; 1132243791Sdim 1133243791Sdim // Method arguments. 1134243791Sdim for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 1135243791Sdim E = OMD->param_end(); PI != E; ++PI) { 1136243791Sdim ParmVarDecl *PDecl = *PI; 1137243791Sdim ResultStr += ", "; 1138243791Sdim if (PDecl->getType()->isObjCQualifiedIdType()) { 1139243791Sdim ResultStr += "id "; 1140243791Sdim ResultStr += PDecl->getNameAsString(); 1141243791Sdim } else { 1142243791Sdim std::string Name = PDecl->getNameAsString(); 1143243791Sdim QualType QT = PDecl->getType(); 1144243791Sdim // Make sure we convert "t (^)(...)" to "t (*)(...)". 1145243791Sdim (void)convertBlockPointerToFunctionPointer(QT); 1146243791Sdim QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 1147243791Sdim ResultStr += Name; 1148243791Sdim } 1149243791Sdim } 1150243791Sdim if (OMD->isVariadic()) 1151243791Sdim ResultStr += ", ..."; 1152243791Sdim ResultStr += ") "; 1153243791Sdim 1154243791Sdim if (FPRetType) { 1155243791Sdim ResultStr += ")"; // close the precedence "scope" for "*". 1156243791Sdim 1157243791Sdim // Now, emit the argument types (if any). 1158243791Sdim if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { 1159243791Sdim ResultStr += "("; 1160243791Sdim for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 1161243791Sdim if (i) ResultStr += ", "; 1162243791Sdim std::string ParamStr = FT->getArgType(i).getAsString( 1163243791Sdim Context->getPrintingPolicy()); 1164243791Sdim ResultStr += ParamStr; 1165243791Sdim } 1166243791Sdim if (FT->isVariadic()) { 1167243791Sdim if (FT->getNumArgs()) ResultStr += ", "; 1168243791Sdim ResultStr += "..."; 1169243791Sdim } 1170243791Sdim ResultStr += ")"; 1171243791Sdim } else { 1172243791Sdim ResultStr += "()"; 1173243791Sdim } 1174243791Sdim } 1175243791Sdim} 1176243791Sdimvoid RewriteObjC::RewriteImplementationDecl(Decl *OID) { 1177243791Sdim ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); 1178243791Sdim ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); 1179243791Sdim 1180243791Sdim InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// "); 1181243791Sdim 1182243791Sdim for (ObjCCategoryImplDecl::instmeth_iterator 1183243791Sdim I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), 1184243791Sdim E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); 1185243791Sdim I != E; ++I) { 1186243791Sdim std::string ResultStr; 1187243791Sdim ObjCMethodDecl *OMD = *I; 1188243791Sdim RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 1189243791Sdim SourceLocation LocStart = OMD->getLocStart(); 1190243791Sdim SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 1191243791Sdim 1192243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 1193243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 1194243791Sdim ReplaceText(LocStart, endBuf-startBuf, ResultStr); 1195243791Sdim } 1196243791Sdim 1197243791Sdim for (ObjCCategoryImplDecl::classmeth_iterator 1198243791Sdim I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), 1199243791Sdim E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); 1200243791Sdim I != E; ++I) { 1201243791Sdim std::string ResultStr; 1202243791Sdim ObjCMethodDecl *OMD = *I; 1203243791Sdim RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 1204243791Sdim SourceLocation LocStart = OMD->getLocStart(); 1205243791Sdim SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 1206243791Sdim 1207243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 1208243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 1209243791Sdim ReplaceText(LocStart, endBuf-startBuf, ResultStr); 1210243791Sdim } 1211243791Sdim for (ObjCCategoryImplDecl::propimpl_iterator 1212243791Sdim I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), 1213243791Sdim E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); 1214243791Sdim I != E; ++I) { 1215243791Sdim RewritePropertyImplDecl(*I, IMD, CID); 1216243791Sdim } 1217243791Sdim 1218243791Sdim InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// "); 1219243791Sdim} 1220243791Sdim 1221243791Sdimvoid RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 1222243791Sdim std::string ResultStr; 1223243791Sdim if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) { 1224243791Sdim // we haven't seen a forward decl - generate a typedef. 1225243791Sdim ResultStr = "#ifndef _REWRITER_typedef_"; 1226243791Sdim ResultStr += ClassDecl->getNameAsString(); 1227243791Sdim ResultStr += "\n"; 1228243791Sdim ResultStr += "#define _REWRITER_typedef_"; 1229243791Sdim ResultStr += ClassDecl->getNameAsString(); 1230243791Sdim ResultStr += "\n"; 1231243791Sdim ResultStr += "typedef struct objc_object "; 1232243791Sdim ResultStr += ClassDecl->getNameAsString(); 1233243791Sdim ResultStr += ";\n#endif\n"; 1234243791Sdim // Mark this typedef as having been generated. 1235243791Sdim ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl()); 1236243791Sdim } 1237243791Sdim RewriteObjCInternalStruct(ClassDecl, ResultStr); 1238243791Sdim 1239243791Sdim for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), 1240243791Sdim E = ClassDecl->prop_end(); I != E; ++I) 1241243791Sdim RewriteProperty(*I); 1242243791Sdim for (ObjCInterfaceDecl::instmeth_iterator 1243243791Sdim I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); 1244243791Sdim I != E; ++I) 1245243791Sdim RewriteMethodDeclaration(*I); 1246243791Sdim for (ObjCInterfaceDecl::classmeth_iterator 1247243791Sdim I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); 1248243791Sdim I != E; ++I) 1249243791Sdim RewriteMethodDeclaration(*I); 1250243791Sdim 1251243791Sdim // Lastly, comment out the @end. 1252243791Sdim ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), 1253243791Sdim "/* @end */"); 1254243791Sdim} 1255243791Sdim 1256243791SdimStmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) { 1257243791Sdim SourceRange OldRange = PseudoOp->getSourceRange(); 1258243791Sdim 1259243791Sdim // We just magically know some things about the structure of this 1260243791Sdim // expression. 1261243791Sdim ObjCMessageExpr *OldMsg = 1262243791Sdim cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr( 1263243791Sdim PseudoOp->getNumSemanticExprs() - 1)); 1264243791Sdim 1265243791Sdim // Because the rewriter doesn't allow us to rewrite rewritten code, 1266243791Sdim // we need to suppress rewriting the sub-statements. 1267243791Sdim Expr *Base, *RHS; 1268243791Sdim { 1269243791Sdim DisableReplaceStmtScope S(*this); 1270243791Sdim 1271243791Sdim // Rebuild the base expression if we have one. 1272243791Sdim Base = 0; 1273243791Sdim if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 1274243791Sdim Base = OldMsg->getInstanceReceiver(); 1275243791Sdim Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 1276243791Sdim Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 1277243791Sdim } 1278243791Sdim 1279243791Sdim // Rebuild the RHS. 1280243791Sdim RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS(); 1281243791Sdim RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr(); 1282243791Sdim RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS)); 1283243791Sdim } 1284243791Sdim 1285243791Sdim // TODO: avoid this copy. 1286243791Sdim SmallVector<SourceLocation, 1> SelLocs; 1287243791Sdim OldMsg->getSelectorLocs(SelLocs); 1288243791Sdim 1289243791Sdim ObjCMessageExpr *NewMsg = 0; 1290243791Sdim switch (OldMsg->getReceiverKind()) { 1291243791Sdim case ObjCMessageExpr::Class: 1292243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1293243791Sdim OldMsg->getValueKind(), 1294243791Sdim OldMsg->getLeftLoc(), 1295243791Sdim OldMsg->getClassReceiverTypeInfo(), 1296243791Sdim OldMsg->getSelector(), 1297243791Sdim SelLocs, 1298243791Sdim OldMsg->getMethodDecl(), 1299243791Sdim RHS, 1300243791Sdim OldMsg->getRightLoc(), 1301243791Sdim OldMsg->isImplicit()); 1302243791Sdim break; 1303243791Sdim 1304243791Sdim case ObjCMessageExpr::Instance: 1305243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1306243791Sdim OldMsg->getValueKind(), 1307243791Sdim OldMsg->getLeftLoc(), 1308243791Sdim Base, 1309243791Sdim OldMsg->getSelector(), 1310243791Sdim SelLocs, 1311243791Sdim OldMsg->getMethodDecl(), 1312243791Sdim RHS, 1313243791Sdim OldMsg->getRightLoc(), 1314243791Sdim OldMsg->isImplicit()); 1315243791Sdim break; 1316243791Sdim 1317243791Sdim case ObjCMessageExpr::SuperClass: 1318243791Sdim case ObjCMessageExpr::SuperInstance: 1319243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1320243791Sdim OldMsg->getValueKind(), 1321243791Sdim OldMsg->getLeftLoc(), 1322243791Sdim OldMsg->getSuperLoc(), 1323243791Sdim OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 1324243791Sdim OldMsg->getSuperType(), 1325243791Sdim OldMsg->getSelector(), 1326243791Sdim SelLocs, 1327243791Sdim OldMsg->getMethodDecl(), 1328243791Sdim RHS, 1329243791Sdim OldMsg->getRightLoc(), 1330243791Sdim OldMsg->isImplicit()); 1331243791Sdim break; 1332243791Sdim } 1333243791Sdim 1334243791Sdim Stmt *Replacement = SynthMessageExpr(NewMsg); 1335243791Sdim ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 1336243791Sdim return Replacement; 1337243791Sdim} 1338243791Sdim 1339243791SdimStmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) { 1340243791Sdim SourceRange OldRange = PseudoOp->getSourceRange(); 1341243791Sdim 1342243791Sdim // We just magically know some things about the structure of this 1343243791Sdim // expression. 1344243791Sdim ObjCMessageExpr *OldMsg = 1345243791Sdim cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit()); 1346243791Sdim 1347243791Sdim // Because the rewriter doesn't allow us to rewrite rewritten code, 1348243791Sdim // we need to suppress rewriting the sub-statements. 1349243791Sdim Expr *Base = 0; 1350243791Sdim { 1351243791Sdim DisableReplaceStmtScope S(*this); 1352243791Sdim 1353243791Sdim // Rebuild the base expression if we have one. 1354243791Sdim if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 1355243791Sdim Base = OldMsg->getInstanceReceiver(); 1356243791Sdim Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 1357243791Sdim Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 1358243791Sdim } 1359243791Sdim } 1360243791Sdim 1361243791Sdim // Intentionally empty. 1362243791Sdim SmallVector<SourceLocation, 1> SelLocs; 1363243791Sdim SmallVector<Expr*, 1> Args; 1364243791Sdim 1365243791Sdim ObjCMessageExpr *NewMsg = 0; 1366243791Sdim switch (OldMsg->getReceiverKind()) { 1367243791Sdim case ObjCMessageExpr::Class: 1368243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1369243791Sdim OldMsg->getValueKind(), 1370243791Sdim OldMsg->getLeftLoc(), 1371243791Sdim OldMsg->getClassReceiverTypeInfo(), 1372243791Sdim OldMsg->getSelector(), 1373243791Sdim SelLocs, 1374243791Sdim OldMsg->getMethodDecl(), 1375243791Sdim Args, 1376243791Sdim OldMsg->getRightLoc(), 1377243791Sdim OldMsg->isImplicit()); 1378243791Sdim break; 1379243791Sdim 1380243791Sdim case ObjCMessageExpr::Instance: 1381243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1382243791Sdim OldMsg->getValueKind(), 1383243791Sdim OldMsg->getLeftLoc(), 1384243791Sdim Base, 1385243791Sdim OldMsg->getSelector(), 1386243791Sdim SelLocs, 1387243791Sdim OldMsg->getMethodDecl(), 1388243791Sdim Args, 1389243791Sdim OldMsg->getRightLoc(), 1390243791Sdim OldMsg->isImplicit()); 1391243791Sdim break; 1392243791Sdim 1393243791Sdim case ObjCMessageExpr::SuperClass: 1394243791Sdim case ObjCMessageExpr::SuperInstance: 1395243791Sdim NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 1396243791Sdim OldMsg->getValueKind(), 1397243791Sdim OldMsg->getLeftLoc(), 1398243791Sdim OldMsg->getSuperLoc(), 1399243791Sdim OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 1400243791Sdim OldMsg->getSuperType(), 1401243791Sdim OldMsg->getSelector(), 1402243791Sdim SelLocs, 1403243791Sdim OldMsg->getMethodDecl(), 1404243791Sdim Args, 1405243791Sdim OldMsg->getRightLoc(), 1406243791Sdim OldMsg->isImplicit()); 1407243791Sdim break; 1408243791Sdim } 1409243791Sdim 1410243791Sdim Stmt *Replacement = SynthMessageExpr(NewMsg); 1411243791Sdim ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 1412243791Sdim return Replacement; 1413243791Sdim} 1414243791Sdim 1415243791Sdim/// SynthCountByEnumWithState - To print: 1416243791Sdim/// ((unsigned int (*) 1417243791Sdim/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 1418243791Sdim/// (void *)objc_msgSend)((id)l_collection, 1419243791Sdim/// sel_registerName( 1420243791Sdim/// "countByEnumeratingWithState:objects:count:"), 1421243791Sdim/// &enumState, 1422243791Sdim/// (id *)__rw_items, (unsigned int)16) 1423243791Sdim/// 1424243791Sdimvoid RewriteObjC::SynthCountByEnumWithState(std::string &buf) { 1425243791Sdim buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 1426243791Sdim "id *, unsigned int))(void *)objc_msgSend)"; 1427243791Sdim buf += "\n\t\t"; 1428243791Sdim buf += "((id)l_collection,\n\t\t"; 1429243791Sdim buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; 1430243791Sdim buf += "\n\t\t"; 1431243791Sdim buf += "&enumState, " 1432243791Sdim "(id *)__rw_items, (unsigned int)16)"; 1433243791Sdim} 1434243791Sdim 1435243791Sdim/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach 1436243791Sdim/// statement to exit to its outer synthesized loop. 1437243791Sdim/// 1438243791SdimStmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) { 1439243791Sdim if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1440243791Sdim return S; 1441243791Sdim // replace break with goto __break_label 1442243791Sdim std::string buf; 1443243791Sdim 1444243791Sdim SourceLocation startLoc = S->getLocStart(); 1445243791Sdim buf = "goto __break_label_"; 1446243791Sdim buf += utostr(ObjCBcLabelNo.back()); 1447243791Sdim ReplaceText(startLoc, strlen("break"), buf); 1448243791Sdim 1449243791Sdim return 0; 1450243791Sdim} 1451243791Sdim 1452243791Sdim/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach 1453243791Sdim/// statement to continue with its inner synthesized loop. 1454243791Sdim/// 1455243791SdimStmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { 1456243791Sdim if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1457243791Sdim return S; 1458243791Sdim // replace continue with goto __continue_label 1459243791Sdim std::string buf; 1460243791Sdim 1461243791Sdim SourceLocation startLoc = S->getLocStart(); 1462243791Sdim buf = "goto __continue_label_"; 1463243791Sdim buf += utostr(ObjCBcLabelNo.back()); 1464243791Sdim ReplaceText(startLoc, strlen("continue"), buf); 1465243791Sdim 1466243791Sdim return 0; 1467243791Sdim} 1468243791Sdim 1469243791Sdim/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. 1470243791Sdim/// It rewrites: 1471243791Sdim/// for ( type elem in collection) { stmts; } 1472243791Sdim 1473243791Sdim/// Into: 1474243791Sdim/// { 1475243791Sdim/// type elem; 1476243791Sdim/// struct __objcFastEnumerationState enumState = { 0 }; 1477243791Sdim/// id __rw_items[16]; 1478243791Sdim/// id l_collection = (id)collection; 1479243791Sdim/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 1480243791Sdim/// objects:__rw_items count:16]; 1481243791Sdim/// if (limit) { 1482243791Sdim/// unsigned long startMutations = *enumState.mutationsPtr; 1483243791Sdim/// do { 1484243791Sdim/// unsigned long counter = 0; 1485243791Sdim/// do { 1486243791Sdim/// if (startMutations != *enumState.mutationsPtr) 1487243791Sdim/// objc_enumerationMutation(l_collection); 1488243791Sdim/// elem = (type)enumState.itemsPtr[counter++]; 1489243791Sdim/// stmts; 1490243791Sdim/// __continue_label: ; 1491243791Sdim/// } while (counter < limit); 1492243791Sdim/// } while (limit = [l_collection countByEnumeratingWithState:&enumState 1493243791Sdim/// objects:__rw_items count:16]); 1494243791Sdim/// elem = nil; 1495243791Sdim/// __break_label: ; 1496243791Sdim/// } 1497243791Sdim/// else 1498243791Sdim/// elem = nil; 1499243791Sdim/// } 1500243791Sdim/// 1501243791SdimStmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 1502243791Sdim SourceLocation OrigEnd) { 1503243791Sdim assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); 1504243791Sdim assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 1505243791Sdim "ObjCForCollectionStmt Statement stack mismatch"); 1506243791Sdim assert(!ObjCBcLabelNo.empty() && 1507243791Sdim "ObjCForCollectionStmt - Label No stack empty"); 1508243791Sdim 1509243791Sdim SourceLocation startLoc = S->getLocStart(); 1510243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1511243791Sdim StringRef elementName; 1512243791Sdim std::string elementTypeAsString; 1513243791Sdim std::string buf; 1514243791Sdim buf = "\n{\n\t"; 1515243791Sdim if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) { 1516243791Sdim // type elem; 1517243791Sdim NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl()); 1518243791Sdim QualType ElementType = cast<ValueDecl>(D)->getType(); 1519243791Sdim if (ElementType->isObjCQualifiedIdType() || 1520243791Sdim ElementType->isObjCQualifiedInterfaceType()) 1521243791Sdim // Simply use 'id' for all qualified types. 1522243791Sdim elementTypeAsString = "id"; 1523243791Sdim else 1524243791Sdim elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy()); 1525243791Sdim buf += elementTypeAsString; 1526243791Sdim buf += " "; 1527243791Sdim elementName = D->getName(); 1528243791Sdim buf += elementName; 1529243791Sdim buf += ";\n\t"; 1530243791Sdim } 1531243791Sdim else { 1532243791Sdim DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); 1533243791Sdim elementName = DR->getDecl()->getName(); 1534243791Sdim ValueDecl *VD = cast<ValueDecl>(DR->getDecl()); 1535243791Sdim if (VD->getType()->isObjCQualifiedIdType() || 1536243791Sdim VD->getType()->isObjCQualifiedInterfaceType()) 1537243791Sdim // Simply use 'id' for all qualified types. 1538243791Sdim elementTypeAsString = "id"; 1539243791Sdim else 1540243791Sdim elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy()); 1541243791Sdim } 1542243791Sdim 1543243791Sdim // struct __objcFastEnumerationState enumState = { 0 }; 1544243791Sdim buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; 1545243791Sdim // id __rw_items[16]; 1546243791Sdim buf += "id __rw_items[16];\n\t"; 1547243791Sdim // id l_collection = (id) 1548243791Sdim buf += "id l_collection = (id)"; 1549243791Sdim // Find start location of 'collection' the hard way! 1550243791Sdim const char *startCollectionBuf = startBuf; 1551243791Sdim startCollectionBuf += 3; // skip 'for' 1552243791Sdim startCollectionBuf = strchr(startCollectionBuf, '('); 1553243791Sdim startCollectionBuf++; // skip '(' 1554243791Sdim // find 'in' and skip it. 1555243791Sdim while (*startCollectionBuf != ' ' || 1556243791Sdim *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' || 1557243791Sdim (*(startCollectionBuf+3) != ' ' && 1558243791Sdim *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) 1559243791Sdim startCollectionBuf++; 1560243791Sdim startCollectionBuf += 3; 1561243791Sdim 1562243791Sdim // Replace: "for (type element in" with string constructed thus far. 1563243791Sdim ReplaceText(startLoc, startCollectionBuf - startBuf, buf); 1564243791Sdim // Replace ')' in for '(' type elem in collection ')' with ';' 1565243791Sdim SourceLocation rightParenLoc = S->getRParenLoc(); 1566243791Sdim const char *rparenBuf = SM->getCharacterData(rightParenLoc); 1567243791Sdim SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf); 1568243791Sdim buf = ";\n\t"; 1569243791Sdim 1570243791Sdim // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 1571243791Sdim // objects:__rw_items count:16]; 1572243791Sdim // which is synthesized into: 1573243791Sdim // unsigned int limit = 1574243791Sdim // ((unsigned int (*) 1575243791Sdim // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 1576243791Sdim // (void *)objc_msgSend)((id)l_collection, 1577243791Sdim // sel_registerName( 1578243791Sdim // "countByEnumeratingWithState:objects:count:"), 1579243791Sdim // (struct __objcFastEnumerationState *)&state, 1580243791Sdim // (id *)__rw_items, (unsigned int)16); 1581243791Sdim buf += "unsigned long limit =\n\t\t"; 1582243791Sdim SynthCountByEnumWithState(buf); 1583243791Sdim buf += ";\n\t"; 1584243791Sdim /// if (limit) { 1585243791Sdim /// unsigned long startMutations = *enumState.mutationsPtr; 1586243791Sdim /// do { 1587243791Sdim /// unsigned long counter = 0; 1588243791Sdim /// do { 1589243791Sdim /// if (startMutations != *enumState.mutationsPtr) 1590243791Sdim /// objc_enumerationMutation(l_collection); 1591243791Sdim /// elem = (type)enumState.itemsPtr[counter++]; 1592243791Sdim buf += "if (limit) {\n\t"; 1593243791Sdim buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t"; 1594243791Sdim buf += "do {\n\t\t"; 1595243791Sdim buf += "unsigned long counter = 0;\n\t\t"; 1596243791Sdim buf += "do {\n\t\t\t"; 1597243791Sdim buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t"; 1598243791Sdim buf += "objc_enumerationMutation(l_collection);\n\t\t\t"; 1599243791Sdim buf += elementName; 1600243791Sdim buf += " = ("; 1601243791Sdim buf += elementTypeAsString; 1602243791Sdim buf += ")enumState.itemsPtr[counter++];"; 1603243791Sdim // Replace ')' in for '(' type elem in collection ')' with all of these. 1604243791Sdim ReplaceText(lparenLoc, 1, buf); 1605243791Sdim 1606243791Sdim /// __continue_label: ; 1607243791Sdim /// } while (counter < limit); 1608243791Sdim /// } while (limit = [l_collection countByEnumeratingWithState:&enumState 1609243791Sdim /// objects:__rw_items count:16]); 1610243791Sdim /// elem = nil; 1611243791Sdim /// __break_label: ; 1612243791Sdim /// } 1613243791Sdim /// else 1614243791Sdim /// elem = nil; 1615243791Sdim /// } 1616243791Sdim /// 1617243791Sdim buf = ";\n\t"; 1618243791Sdim buf += "__continue_label_"; 1619243791Sdim buf += utostr(ObjCBcLabelNo.back()); 1620243791Sdim buf += ": ;"; 1621243791Sdim buf += "\n\t\t"; 1622243791Sdim buf += "} while (counter < limit);\n\t"; 1623243791Sdim buf += "} while (limit = "; 1624243791Sdim SynthCountByEnumWithState(buf); 1625243791Sdim buf += ");\n\t"; 1626243791Sdim buf += elementName; 1627243791Sdim buf += " = (("; 1628243791Sdim buf += elementTypeAsString; 1629243791Sdim buf += ")0);\n\t"; 1630243791Sdim buf += "__break_label_"; 1631243791Sdim buf += utostr(ObjCBcLabelNo.back()); 1632243791Sdim buf += ": ;\n\t"; 1633243791Sdim buf += "}\n\t"; 1634243791Sdim buf += "else\n\t\t"; 1635243791Sdim buf += elementName; 1636243791Sdim buf += " = (("; 1637243791Sdim buf += elementTypeAsString; 1638243791Sdim buf += ")0);\n\t"; 1639243791Sdim buf += "}\n"; 1640243791Sdim 1641243791Sdim // Insert all these *after* the statement body. 1642243791Sdim // FIXME: If this should support Obj-C++, support CXXTryStmt 1643243791Sdim if (isa<CompoundStmt>(S->getBody())) { 1644243791Sdim SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1); 1645243791Sdim InsertText(endBodyLoc, buf); 1646243791Sdim } else { 1647243791Sdim /* Need to treat single statements specially. For example: 1648243791Sdim * 1649243791Sdim * for (A *a in b) if (stuff()) break; 1650243791Sdim * for (A *a in b) xxxyy; 1651243791Sdim * 1652243791Sdim * The following code simply scans ahead to the semi to find the actual end. 1653243791Sdim */ 1654243791Sdim const char *stmtBuf = SM->getCharacterData(OrigEnd); 1655243791Sdim const char *semiBuf = strchr(stmtBuf, ';'); 1656243791Sdim assert(semiBuf && "Can't find ';'"); 1657243791Sdim SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1); 1658243791Sdim InsertText(endBodyLoc, buf); 1659243791Sdim } 1660243791Sdim Stmts.pop_back(); 1661243791Sdim ObjCBcLabelNo.pop_back(); 1662243791Sdim return 0; 1663243791Sdim} 1664243791Sdim 1665243791Sdim/// RewriteObjCSynchronizedStmt - 1666243791Sdim/// This routine rewrites @synchronized(expr) stmt; 1667243791Sdim/// into: 1668243791Sdim/// objc_sync_enter(expr); 1669243791Sdim/// @try stmt @finally { objc_sync_exit(expr); } 1670243791Sdim/// 1671243791SdimStmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 1672243791Sdim // Get the start location and compute the semi location. 1673243791Sdim SourceLocation startLoc = S->getLocStart(); 1674243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1675243791Sdim 1676243791Sdim assert((*startBuf == '@') && "bogus @synchronized location"); 1677243791Sdim 1678243791Sdim std::string buf; 1679243791Sdim buf = "objc_sync_enter((id)"; 1680243791Sdim const char *lparenBuf = startBuf; 1681243791Sdim while (*lparenBuf != '(') lparenBuf++; 1682243791Sdim ReplaceText(startLoc, lparenBuf-startBuf+1, buf); 1683243791Sdim // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since 1684243791Sdim // the sync expression is typically a message expression that's already 1685243791Sdim // been rewritten! (which implies the SourceLocation's are invalid). 1686243791Sdim SourceLocation endLoc = S->getSynchBody()->getLocStart(); 1687243791Sdim const char *endBuf = SM->getCharacterData(endLoc); 1688243791Sdim while (*endBuf != ')') endBuf--; 1689243791Sdim SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf); 1690243791Sdim buf = ");\n"; 1691243791Sdim // declare a new scope with two variables, _stack and _rethrow. 1692243791Sdim buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n"; 1693243791Sdim buf += "int buf[18/*32-bit i386*/];\n"; 1694243791Sdim buf += "char *pointers[4];} _stack;\n"; 1695243791Sdim buf += "id volatile _rethrow = 0;\n"; 1696243791Sdim buf += "objc_exception_try_enter(&_stack);\n"; 1697243791Sdim buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 1698243791Sdim ReplaceText(rparenLoc, 1, buf); 1699243791Sdim startLoc = S->getSynchBody()->getLocEnd(); 1700243791Sdim startBuf = SM->getCharacterData(startLoc); 1701243791Sdim 1702243791Sdim assert((*startBuf == '}') && "bogus @synchronized block"); 1703243791Sdim SourceLocation lastCurlyLoc = startLoc; 1704243791Sdim buf = "}\nelse {\n"; 1705243791Sdim buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1706243791Sdim buf += "}\n"; 1707243791Sdim buf += "{ /* implicit finally clause */\n"; 1708243791Sdim buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 1709243791Sdim 1710243791Sdim std::string syncBuf; 1711243791Sdim syncBuf += " objc_sync_exit("; 1712243791Sdim 1713243791Sdim Expr *syncExpr = S->getSynchExpr(); 1714243791Sdim CastKind CK = syncExpr->getType()->isObjCObjectPointerType() 1715243791Sdim ? CK_BitCast : 1716243791Sdim syncExpr->getType()->isBlockPointerType() 1717243791Sdim ? CK_BlockPointerToObjCPointerCast 1718243791Sdim : CK_CPointerToObjCPointerCast; 1719243791Sdim syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 1720243791Sdim CK, syncExpr); 1721243791Sdim std::string syncExprBufS; 1722243791Sdim llvm::raw_string_ostream syncExprBuf(syncExprBufS); 1723243791Sdim syncExpr->printPretty(syncExprBuf, 0, PrintingPolicy(LangOpts)); 1724243791Sdim syncBuf += syncExprBuf.str(); 1725243791Sdim syncBuf += ");"; 1726243791Sdim 1727243791Sdim buf += syncBuf; 1728243791Sdim buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n"; 1729243791Sdim buf += "}\n"; 1730243791Sdim buf += "}"; 1731243791Sdim 1732243791Sdim ReplaceText(lastCurlyLoc, 1, buf); 1733243791Sdim 1734243791Sdim bool hasReturns = false; 1735243791Sdim HasReturnStmts(S->getSynchBody(), hasReturns); 1736243791Sdim if (hasReturns) 1737243791Sdim RewriteSyncReturnStmts(S->getSynchBody(), syncBuf); 1738243791Sdim 1739243791Sdim return 0; 1740243791Sdim} 1741243791Sdim 1742243791Sdimvoid RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S) 1743243791Sdim{ 1744243791Sdim // Perform a bottom up traversal of all children. 1745243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 1746243791Sdim if (*CI) 1747243791Sdim WarnAboutReturnGotoStmts(*CI); 1748243791Sdim 1749243791Sdim if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) { 1750243791Sdim Diags.Report(Context->getFullLoc(S->getLocStart()), 1751243791Sdim TryFinallyContainsReturnDiag); 1752243791Sdim } 1753243791Sdim return; 1754243791Sdim} 1755243791Sdim 1756243791Sdimvoid RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns) 1757243791Sdim{ 1758243791Sdim // Perform a bottom up traversal of all children. 1759243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 1760243791Sdim if (*CI) 1761243791Sdim HasReturnStmts(*CI, hasReturns); 1762243791Sdim 1763243791Sdim if (isa<ReturnStmt>(S)) 1764243791Sdim hasReturns = true; 1765243791Sdim return; 1766243791Sdim} 1767243791Sdim 1768243791Sdimvoid RewriteObjC::RewriteTryReturnStmts(Stmt *S) { 1769243791Sdim // Perform a bottom up traversal of all children. 1770243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 1771243791Sdim if (*CI) { 1772243791Sdim RewriteTryReturnStmts(*CI); 1773243791Sdim } 1774243791Sdim if (isa<ReturnStmt>(S)) { 1775243791Sdim SourceLocation startLoc = S->getLocStart(); 1776243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1777243791Sdim 1778243791Sdim const char *semiBuf = strchr(startBuf, ';'); 1779243791Sdim assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'"); 1780243791Sdim SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 1781243791Sdim 1782243791Sdim std::string buf; 1783243791Sdim buf = "{ objc_exception_try_exit(&_stack); return"; 1784243791Sdim 1785243791Sdim ReplaceText(startLoc, 6, buf); 1786243791Sdim InsertText(onePastSemiLoc, "}"); 1787243791Sdim } 1788243791Sdim return; 1789243791Sdim} 1790243791Sdim 1791243791Sdimvoid RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) { 1792243791Sdim // Perform a bottom up traversal of all children. 1793243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 1794243791Sdim if (*CI) { 1795243791Sdim RewriteSyncReturnStmts(*CI, syncExitBuf); 1796243791Sdim } 1797243791Sdim if (isa<ReturnStmt>(S)) { 1798243791Sdim SourceLocation startLoc = S->getLocStart(); 1799243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1800243791Sdim 1801243791Sdim const char *semiBuf = strchr(startBuf, ';'); 1802243791Sdim assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'"); 1803243791Sdim SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 1804243791Sdim 1805243791Sdim std::string buf; 1806243791Sdim buf = "{ objc_exception_try_exit(&_stack);"; 1807243791Sdim buf += syncExitBuf; 1808243791Sdim buf += " return"; 1809243791Sdim 1810243791Sdim ReplaceText(startLoc, 6, buf); 1811243791Sdim InsertText(onePastSemiLoc, "}"); 1812243791Sdim } 1813243791Sdim return; 1814243791Sdim} 1815243791Sdim 1816243791SdimStmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { 1817243791Sdim // Get the start location and compute the semi location. 1818243791Sdim SourceLocation startLoc = S->getLocStart(); 1819243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1820243791Sdim 1821243791Sdim assert((*startBuf == '@') && "bogus @try location"); 1822243791Sdim 1823243791Sdim std::string buf; 1824243791Sdim // declare a new scope with two variables, _stack and _rethrow. 1825243791Sdim buf = "/* @try scope begin */ { struct _objc_exception_data {\n"; 1826243791Sdim buf += "int buf[18/*32-bit i386*/];\n"; 1827243791Sdim buf += "char *pointers[4];} _stack;\n"; 1828243791Sdim buf += "id volatile _rethrow = 0;\n"; 1829243791Sdim buf += "objc_exception_try_enter(&_stack);\n"; 1830243791Sdim buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 1831243791Sdim 1832243791Sdim ReplaceText(startLoc, 4, buf); 1833243791Sdim 1834243791Sdim startLoc = S->getTryBody()->getLocEnd(); 1835243791Sdim startBuf = SM->getCharacterData(startLoc); 1836243791Sdim 1837243791Sdim assert((*startBuf == '}') && "bogus @try block"); 1838243791Sdim 1839243791Sdim SourceLocation lastCurlyLoc = startLoc; 1840243791Sdim if (S->getNumCatchStmts()) { 1841243791Sdim startLoc = startLoc.getLocWithOffset(1); 1842243791Sdim buf = " /* @catch begin */ else {\n"; 1843243791Sdim buf += " id _caught = objc_exception_extract(&_stack);\n"; 1844243791Sdim buf += " objc_exception_try_enter (&_stack);\n"; 1845243791Sdim buf += " if (_setjmp(_stack.buf))\n"; 1846243791Sdim buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1847243791Sdim buf += " else { /* @catch continue */"; 1848243791Sdim 1849243791Sdim InsertText(startLoc, buf); 1850243791Sdim } else { /* no catch list */ 1851243791Sdim buf = "}\nelse {\n"; 1852243791Sdim buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1853243791Sdim buf += "}"; 1854243791Sdim ReplaceText(lastCurlyLoc, 1, buf); 1855243791Sdim } 1856243791Sdim Stmt *lastCatchBody = 0; 1857243791Sdim for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { 1858243791Sdim ObjCAtCatchStmt *Catch = S->getCatchStmt(I); 1859243791Sdim VarDecl *catchDecl = Catch->getCatchParamDecl(); 1860243791Sdim 1861243791Sdim if (I == 0) 1862243791Sdim buf = "if ("; // we are generating code for the first catch clause 1863243791Sdim else 1864243791Sdim buf = "else if ("; 1865243791Sdim startLoc = Catch->getLocStart(); 1866243791Sdim startBuf = SM->getCharacterData(startLoc); 1867243791Sdim 1868243791Sdim assert((*startBuf == '@') && "bogus @catch location"); 1869243791Sdim 1870243791Sdim const char *lParenLoc = strchr(startBuf, '('); 1871243791Sdim 1872243791Sdim if (Catch->hasEllipsis()) { 1873243791Sdim // Now rewrite the body... 1874243791Sdim lastCatchBody = Catch->getCatchBody(); 1875243791Sdim SourceLocation bodyLoc = lastCatchBody->getLocStart(); 1876243791Sdim const char *bodyBuf = SM->getCharacterData(bodyLoc); 1877243791Sdim assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' && 1878243791Sdim "bogus @catch paren location"); 1879243791Sdim assert((*bodyBuf == '{') && "bogus @catch body location"); 1880243791Sdim 1881243791Sdim buf += "1) { id _tmp = _caught;"; 1882243791Sdim Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf); 1883243791Sdim } else if (catchDecl) { 1884243791Sdim QualType t = catchDecl->getType(); 1885243791Sdim if (t == Context->getObjCIdType()) { 1886243791Sdim buf += "1) { "; 1887243791Sdim ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 1888243791Sdim } else if (const ObjCObjectPointerType *Ptr = 1889243791Sdim t->getAs<ObjCObjectPointerType>()) { 1890243791Sdim // Should be a pointer to a class. 1891243791Sdim ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface(); 1892243791Sdim if (IDecl) { 1893243791Sdim buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; 1894243791Sdim buf += IDecl->getNameAsString(); 1895243791Sdim buf += "\"), (struct objc_object *)_caught)) { "; 1896243791Sdim ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 1897243791Sdim } 1898243791Sdim } 1899243791Sdim // Now rewrite the body... 1900243791Sdim lastCatchBody = Catch->getCatchBody(); 1901243791Sdim SourceLocation rParenLoc = Catch->getRParenLoc(); 1902243791Sdim SourceLocation bodyLoc = lastCatchBody->getLocStart(); 1903243791Sdim const char *bodyBuf = SM->getCharacterData(bodyLoc); 1904243791Sdim const char *rParenBuf = SM->getCharacterData(rParenLoc); 1905243791Sdim assert((*rParenBuf == ')') && "bogus @catch paren location"); 1906243791Sdim assert((*bodyBuf == '{') && "bogus @catch body location"); 1907243791Sdim 1908243791Sdim // Here we replace ") {" with "= _caught;" (which initializes and 1909243791Sdim // declares the @catch parameter). 1910243791Sdim ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;"); 1911243791Sdim } else { 1912243791Sdim llvm_unreachable("@catch rewrite bug"); 1913243791Sdim } 1914243791Sdim } 1915243791Sdim // Complete the catch list... 1916243791Sdim if (lastCatchBody) { 1917243791Sdim SourceLocation bodyLoc = lastCatchBody->getLocEnd(); 1918243791Sdim assert(*SM->getCharacterData(bodyLoc) == '}' && 1919243791Sdim "bogus @catch body location"); 1920243791Sdim 1921243791Sdim // Insert the last (implicit) else clause *before* the right curly brace. 1922243791Sdim bodyLoc = bodyLoc.getLocWithOffset(-1); 1923243791Sdim buf = "} /* last catch end */\n"; 1924243791Sdim buf += "else {\n"; 1925243791Sdim buf += " _rethrow = _caught;\n"; 1926243791Sdim buf += " objc_exception_try_exit(&_stack);\n"; 1927243791Sdim buf += "} } /* @catch end */\n"; 1928243791Sdim if (!S->getFinallyStmt()) 1929243791Sdim buf += "}\n"; 1930243791Sdim InsertText(bodyLoc, buf); 1931243791Sdim 1932243791Sdim // Set lastCurlyLoc 1933243791Sdim lastCurlyLoc = lastCatchBody->getLocEnd(); 1934243791Sdim } 1935243791Sdim if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) { 1936243791Sdim startLoc = finalStmt->getLocStart(); 1937243791Sdim startBuf = SM->getCharacterData(startLoc); 1938243791Sdim assert((*startBuf == '@') && "bogus @finally start"); 1939243791Sdim 1940243791Sdim ReplaceText(startLoc, 8, "/* @finally */"); 1941243791Sdim 1942243791Sdim Stmt *body = finalStmt->getFinallyBody(); 1943243791Sdim SourceLocation startLoc = body->getLocStart(); 1944243791Sdim SourceLocation endLoc = body->getLocEnd(); 1945243791Sdim assert(*SM->getCharacterData(startLoc) == '{' && 1946243791Sdim "bogus @finally body location"); 1947243791Sdim assert(*SM->getCharacterData(endLoc) == '}' && 1948243791Sdim "bogus @finally body location"); 1949243791Sdim 1950243791Sdim startLoc = startLoc.getLocWithOffset(1); 1951243791Sdim InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n"); 1952243791Sdim endLoc = endLoc.getLocWithOffset(-1); 1953243791Sdim InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n"); 1954243791Sdim 1955243791Sdim // Set lastCurlyLoc 1956243791Sdim lastCurlyLoc = body->getLocEnd(); 1957243791Sdim 1958243791Sdim // Now check for any return/continue/go statements within the @try. 1959243791Sdim WarnAboutReturnGotoStmts(S->getTryBody()); 1960243791Sdim } else { /* no finally clause - make sure we synthesize an implicit one */ 1961243791Sdim buf = "{ /* implicit finally clause */\n"; 1962243791Sdim buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 1963243791Sdim buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; 1964243791Sdim buf += "}"; 1965243791Sdim ReplaceText(lastCurlyLoc, 1, buf); 1966243791Sdim 1967243791Sdim // Now check for any return/continue/go statements within the @try. 1968243791Sdim // The implicit finally clause won't called if the @try contains any 1969243791Sdim // jump statements. 1970243791Sdim bool hasReturns = false; 1971243791Sdim HasReturnStmts(S->getTryBody(), hasReturns); 1972243791Sdim if (hasReturns) 1973243791Sdim RewriteTryReturnStmts(S->getTryBody()); 1974243791Sdim } 1975243791Sdim // Now emit the final closing curly brace... 1976243791Sdim lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1); 1977243791Sdim InsertText(lastCurlyLoc, " } /* @try scope end */\n"); 1978243791Sdim return 0; 1979243791Sdim} 1980243791Sdim 1981243791Sdim// This can't be done with ReplaceStmt(S, ThrowExpr), since 1982243791Sdim// the throw expression is typically a message expression that's already 1983243791Sdim// been rewritten! (which implies the SourceLocation's are invalid). 1984243791SdimStmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { 1985243791Sdim // Get the start location and compute the semi location. 1986243791Sdim SourceLocation startLoc = S->getLocStart(); 1987243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 1988243791Sdim 1989243791Sdim assert((*startBuf == '@') && "bogus @throw location"); 1990243791Sdim 1991243791Sdim std::string buf; 1992243791Sdim /* void objc_exception_throw(id) __attribute__((noreturn)); */ 1993243791Sdim if (S->getThrowExpr()) 1994243791Sdim buf = "objc_exception_throw("; 1995243791Sdim else // add an implicit argument 1996243791Sdim buf = "objc_exception_throw(_caught"; 1997243791Sdim 1998243791Sdim // handle "@ throw" correctly. 1999243791Sdim const char *wBuf = strchr(startBuf, 'w'); 2000243791Sdim assert((*wBuf == 'w') && "@throw: can't find 'w'"); 2001243791Sdim ReplaceText(startLoc, wBuf-startBuf+1, buf); 2002243791Sdim 2003243791Sdim const char *semiBuf = strchr(startBuf, ';'); 2004243791Sdim assert((*semiBuf == ';') && "@throw: can't find ';'"); 2005243791Sdim SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf); 2006243791Sdim ReplaceText(semiLoc, 1, ");"); 2007243791Sdim return 0; 2008243791Sdim} 2009243791Sdim 2010243791SdimStmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { 2011243791Sdim // Create a new string expression. 2012243791Sdim QualType StrType = Context->getPointerType(Context->CharTy); 2013243791Sdim std::string StrEncoding; 2014243791Sdim Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); 2015243791Sdim Expr *Replacement = StringLiteral::Create(*Context, StrEncoding, 2016243791Sdim StringLiteral::Ascii, false, 2017243791Sdim StrType, SourceLocation()); 2018243791Sdim ReplaceStmt(Exp, Replacement); 2019243791Sdim 2020243791Sdim // Replace this subexpr in the parent. 2021243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2022243791Sdim return Replacement; 2023243791Sdim} 2024243791Sdim 2025243791SdimStmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { 2026243791Sdim if (!SelGetUidFunctionDecl) 2027243791Sdim SynthSelGetUidFunctionDecl(); 2028243791Sdim assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl"); 2029243791Sdim // Create a call to sel_registerName("selName"). 2030243791Sdim SmallVector<Expr*, 8> SelExprs; 2031243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2032243791Sdim SelExprs.push_back(StringLiteral::Create(*Context, 2033243791Sdim Exp->getSelector().getAsString(), 2034243791Sdim StringLiteral::Ascii, false, 2035243791Sdim argType, SourceLocation())); 2036243791Sdim CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 2037243791Sdim &SelExprs[0], SelExprs.size()); 2038243791Sdim ReplaceStmt(Exp, SelExp); 2039243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2040243791Sdim return SelExp; 2041243791Sdim} 2042243791Sdim 2043243791SdimCallExpr *RewriteObjC::SynthesizeCallToFunctionDecl( 2044243791Sdim FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc, 2045243791Sdim SourceLocation EndLoc) { 2046243791Sdim // Get the type, we will need to reference it in a couple spots. 2047243791Sdim QualType msgSendType = FD->getType(); 2048243791Sdim 2049243791Sdim // Create a reference to the objc_msgSend() declaration. 2050243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, msgSendType, 2051243791Sdim VK_LValue, SourceLocation()); 2052243791Sdim 2053243791Sdim // Now, we cast the reference to a pointer to the objc_msgSend type. 2054243791Sdim QualType pToFunc = Context->getPointerType(msgSendType); 2055243791Sdim ImplicitCastExpr *ICE = 2056243791Sdim ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, 2057243791Sdim DRE, 0, VK_RValue); 2058243791Sdim 2059243791Sdim const FunctionType *FT = msgSendType->getAs<FunctionType>(); 2060243791Sdim 2061243791Sdim CallExpr *Exp = 2062243791Sdim new (Context) CallExpr(*Context, ICE, llvm::makeArrayRef(args, nargs), 2063243791Sdim FT->getCallResultType(*Context), 2064243791Sdim VK_RValue, EndLoc); 2065243791Sdim return Exp; 2066243791Sdim} 2067243791Sdim 2068243791Sdimstatic bool scanForProtocolRefs(const char *startBuf, const char *endBuf, 2069243791Sdim const char *&startRef, const char *&endRef) { 2070243791Sdim while (startBuf < endBuf) { 2071243791Sdim if (*startBuf == '<') 2072243791Sdim startRef = startBuf; // mark the start. 2073243791Sdim if (*startBuf == '>') { 2074243791Sdim if (startRef && *startRef == '<') { 2075243791Sdim endRef = startBuf; // mark the end. 2076243791Sdim return true; 2077243791Sdim } 2078243791Sdim return false; 2079243791Sdim } 2080243791Sdim startBuf++; 2081243791Sdim } 2082243791Sdim return false; 2083243791Sdim} 2084243791Sdim 2085243791Sdimstatic void scanToNextArgument(const char *&argRef) { 2086243791Sdim int angle = 0; 2087243791Sdim while (*argRef != ')' && (*argRef != ',' || angle > 0)) { 2088243791Sdim if (*argRef == '<') 2089243791Sdim angle++; 2090243791Sdim else if (*argRef == '>') 2091243791Sdim angle--; 2092243791Sdim argRef++; 2093243791Sdim } 2094243791Sdim assert(angle == 0 && "scanToNextArgument - bad protocol type syntax"); 2095243791Sdim} 2096243791Sdim 2097243791Sdimbool RewriteObjC::needToScanForQualifiers(QualType T) { 2098243791Sdim if (T->isObjCQualifiedIdType()) 2099243791Sdim return true; 2100243791Sdim if (const PointerType *PT = T->getAs<PointerType>()) { 2101243791Sdim if (PT->getPointeeType()->isObjCQualifiedIdType()) 2102243791Sdim return true; 2103243791Sdim } 2104243791Sdim if (T->isObjCObjectPointerType()) { 2105243791Sdim T = T->getPointeeType(); 2106243791Sdim return T->isObjCQualifiedInterfaceType(); 2107243791Sdim } 2108243791Sdim if (T->isArrayType()) { 2109243791Sdim QualType ElemTy = Context->getBaseElementType(T); 2110243791Sdim return needToScanForQualifiers(ElemTy); 2111243791Sdim } 2112243791Sdim return false; 2113243791Sdim} 2114243791Sdim 2115243791Sdimvoid RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { 2116243791Sdim QualType Type = E->getType(); 2117243791Sdim if (needToScanForQualifiers(Type)) { 2118243791Sdim SourceLocation Loc, EndLoc; 2119243791Sdim 2120243791Sdim if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { 2121243791Sdim Loc = ECE->getLParenLoc(); 2122243791Sdim EndLoc = ECE->getRParenLoc(); 2123243791Sdim } else { 2124243791Sdim Loc = E->getLocStart(); 2125243791Sdim EndLoc = E->getLocEnd(); 2126243791Sdim } 2127243791Sdim // This will defend against trying to rewrite synthesized expressions. 2128243791Sdim if (Loc.isInvalid() || EndLoc.isInvalid()) 2129243791Sdim return; 2130243791Sdim 2131243791Sdim const char *startBuf = SM->getCharacterData(Loc); 2132243791Sdim const char *endBuf = SM->getCharacterData(EndLoc); 2133243791Sdim const char *startRef = 0, *endRef = 0; 2134243791Sdim if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2135243791Sdim // Get the locations of the startRef, endRef. 2136243791Sdim SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf); 2137243791Sdim SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1); 2138243791Sdim // Comment out the protocol references. 2139243791Sdim InsertText(LessLoc, "/*"); 2140243791Sdim InsertText(GreaterLoc, "*/"); 2141243791Sdim } 2142243791Sdim } 2143243791Sdim} 2144243791Sdim 2145243791Sdimvoid RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { 2146243791Sdim SourceLocation Loc; 2147243791Sdim QualType Type; 2148243791Sdim const FunctionProtoType *proto = 0; 2149243791Sdim if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) { 2150243791Sdim Loc = VD->getLocation(); 2151243791Sdim Type = VD->getType(); 2152243791Sdim } 2153243791Sdim else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) { 2154243791Sdim Loc = FD->getLocation(); 2155243791Sdim // Check for ObjC 'id' and class types that have been adorned with protocol 2156243791Sdim // information (id<p>, C<p>*). The protocol references need to be rewritten! 2157243791Sdim const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 2158243791Sdim assert(funcType && "missing function type"); 2159243791Sdim proto = dyn_cast<FunctionProtoType>(funcType); 2160243791Sdim if (!proto) 2161243791Sdim return; 2162243791Sdim Type = proto->getResultType(); 2163243791Sdim } 2164243791Sdim else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) { 2165243791Sdim Loc = FD->getLocation(); 2166243791Sdim Type = FD->getType(); 2167243791Sdim } 2168243791Sdim else 2169243791Sdim return; 2170243791Sdim 2171243791Sdim if (needToScanForQualifiers(Type)) { 2172243791Sdim // Since types are unique, we need to scan the buffer. 2173243791Sdim 2174243791Sdim const char *endBuf = SM->getCharacterData(Loc); 2175243791Sdim const char *startBuf = endBuf; 2176243791Sdim while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) 2177243791Sdim startBuf--; // scan backward (from the decl location) for return type. 2178243791Sdim const char *startRef = 0, *endRef = 0; 2179243791Sdim if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2180243791Sdim // Get the locations of the startRef, endRef. 2181243791Sdim SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf); 2182243791Sdim SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1); 2183243791Sdim // Comment out the protocol references. 2184243791Sdim InsertText(LessLoc, "/*"); 2185243791Sdim InsertText(GreaterLoc, "*/"); 2186243791Sdim } 2187243791Sdim } 2188243791Sdim if (!proto) 2189243791Sdim return; // most likely, was a variable 2190243791Sdim // Now check arguments. 2191243791Sdim const char *startBuf = SM->getCharacterData(Loc); 2192243791Sdim const char *startFuncBuf = startBuf; 2193243791Sdim for (unsigned i = 0; i < proto->getNumArgs(); i++) { 2194243791Sdim if (needToScanForQualifiers(proto->getArgType(i))) { 2195243791Sdim // Since types are unique, we need to scan the buffer. 2196243791Sdim 2197243791Sdim const char *endBuf = startBuf; 2198243791Sdim // scan forward (from the decl location) for argument types. 2199243791Sdim scanToNextArgument(endBuf); 2200243791Sdim const char *startRef = 0, *endRef = 0; 2201243791Sdim if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2202243791Sdim // Get the locations of the startRef, endRef. 2203243791Sdim SourceLocation LessLoc = 2204243791Sdim Loc.getLocWithOffset(startRef-startFuncBuf); 2205243791Sdim SourceLocation GreaterLoc = 2206243791Sdim Loc.getLocWithOffset(endRef-startFuncBuf+1); 2207243791Sdim // Comment out the protocol references. 2208243791Sdim InsertText(LessLoc, "/*"); 2209243791Sdim InsertText(GreaterLoc, "*/"); 2210243791Sdim } 2211243791Sdim startBuf = ++endBuf; 2212243791Sdim } 2213243791Sdim else { 2214243791Sdim // If the function name is derived from a macro expansion, then the 2215243791Sdim // argument buffer will not follow the name. Need to speak with Chris. 2216243791Sdim while (*startBuf && *startBuf != ')' && *startBuf != ',') 2217243791Sdim startBuf++; // scan forward (from the decl location) for argument types. 2218243791Sdim startBuf++; 2219243791Sdim } 2220243791Sdim } 2221243791Sdim} 2222243791Sdim 2223243791Sdimvoid RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) { 2224243791Sdim QualType QT = ND->getType(); 2225243791Sdim const Type* TypePtr = QT->getAs<Type>(); 2226243791Sdim if (!isa<TypeOfExprType>(TypePtr)) 2227243791Sdim return; 2228243791Sdim while (isa<TypeOfExprType>(TypePtr)) { 2229243791Sdim const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 2230243791Sdim QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 2231243791Sdim TypePtr = QT->getAs<Type>(); 2232243791Sdim } 2233243791Sdim // FIXME. This will not work for multiple declarators; as in: 2234243791Sdim // __typeof__(a) b,c,d; 2235243791Sdim std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy())); 2236243791Sdim SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 2237243791Sdim const char *startBuf = SM->getCharacterData(DeclLoc); 2238243791Sdim if (ND->getInit()) { 2239243791Sdim std::string Name(ND->getNameAsString()); 2240243791Sdim TypeAsString += " " + Name + " = "; 2241243791Sdim Expr *E = ND->getInit(); 2242243791Sdim SourceLocation startLoc; 2243243791Sdim if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 2244243791Sdim startLoc = ECE->getLParenLoc(); 2245243791Sdim else 2246243791Sdim startLoc = E->getLocStart(); 2247243791Sdim startLoc = SM->getExpansionLoc(startLoc); 2248243791Sdim const char *endBuf = SM->getCharacterData(startLoc); 2249243791Sdim ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 2250243791Sdim } 2251243791Sdim else { 2252243791Sdim SourceLocation X = ND->getLocEnd(); 2253243791Sdim X = SM->getExpansionLoc(X); 2254243791Sdim const char *endBuf = SM->getCharacterData(X); 2255243791Sdim ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 2256243791Sdim } 2257243791Sdim} 2258243791Sdim 2259243791Sdim// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); 2260243791Sdimvoid RewriteObjC::SynthSelGetUidFunctionDecl() { 2261243791Sdim IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); 2262243791Sdim SmallVector<QualType, 16> ArgTys; 2263243791Sdim ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2264243791Sdim QualType getFuncType = 2265249423Sdim getSimpleFunctionType(Context->getObjCSelType(), ArgTys); 2266243791Sdim SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2267249423Sdim SourceLocation(), 2268249423Sdim SourceLocation(), 2269249423Sdim SelGetUidIdent, getFuncType, 0, 2270249423Sdim SC_Extern); 2271243791Sdim} 2272243791Sdim 2273243791Sdimvoid RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { 2274243791Sdim // declared in <objc/objc.h> 2275243791Sdim if (FD->getIdentifier() && 2276243791Sdim FD->getName() == "sel_registerName") { 2277243791Sdim SelGetUidFunctionDecl = FD; 2278243791Sdim return; 2279243791Sdim } 2280243791Sdim RewriteObjCQualifiedInterfaceTypes(FD); 2281243791Sdim} 2282243791Sdim 2283243791Sdimvoid RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) { 2284243791Sdim std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 2285243791Sdim const char *argPtr = TypeString.c_str(); 2286243791Sdim if (!strchr(argPtr, '^')) { 2287243791Sdim Str += TypeString; 2288243791Sdim return; 2289243791Sdim } 2290243791Sdim while (*argPtr) { 2291243791Sdim Str += (*argPtr == '^' ? '*' : *argPtr); 2292243791Sdim argPtr++; 2293243791Sdim } 2294243791Sdim} 2295243791Sdim 2296243791Sdim// FIXME. Consolidate this routine with RewriteBlockPointerType. 2297243791Sdimvoid RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str, 2298243791Sdim ValueDecl *VD) { 2299243791Sdim QualType Type = VD->getType(); 2300243791Sdim std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 2301243791Sdim const char *argPtr = TypeString.c_str(); 2302243791Sdim int paren = 0; 2303243791Sdim while (*argPtr) { 2304243791Sdim switch (*argPtr) { 2305243791Sdim case '(': 2306243791Sdim Str += *argPtr; 2307243791Sdim paren++; 2308243791Sdim break; 2309243791Sdim case ')': 2310243791Sdim Str += *argPtr; 2311243791Sdim paren--; 2312243791Sdim break; 2313243791Sdim case '^': 2314243791Sdim Str += '*'; 2315243791Sdim if (paren == 1) 2316243791Sdim Str += VD->getNameAsString(); 2317243791Sdim break; 2318243791Sdim default: 2319243791Sdim Str += *argPtr; 2320243791Sdim break; 2321243791Sdim } 2322243791Sdim argPtr++; 2323243791Sdim } 2324243791Sdim} 2325243791Sdim 2326243791Sdim 2327243791Sdimvoid RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { 2328243791Sdim SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 2329243791Sdim const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 2330243791Sdim const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType); 2331243791Sdim if (!proto) 2332243791Sdim return; 2333243791Sdim QualType Type = proto->getResultType(); 2334243791Sdim std::string FdStr = Type.getAsString(Context->getPrintingPolicy()); 2335243791Sdim FdStr += " "; 2336243791Sdim FdStr += FD->getName(); 2337243791Sdim FdStr += "("; 2338243791Sdim unsigned numArgs = proto->getNumArgs(); 2339243791Sdim for (unsigned i = 0; i < numArgs; i++) { 2340243791Sdim QualType ArgType = proto->getArgType(i); 2341243791Sdim RewriteBlockPointerType(FdStr, ArgType); 2342243791Sdim if (i+1 < numArgs) 2343243791Sdim FdStr += ", "; 2344243791Sdim } 2345243791Sdim FdStr += ");\n"; 2346243791Sdim InsertText(FunLocStart, FdStr); 2347243791Sdim CurFunctionDeclToDeclareForBlock = 0; 2348243791Sdim} 2349243791Sdim 2350263508Sdim// SynthSuperConstructorFunctionDecl - id objc_super(id obj, id super); 2351263508Sdimvoid RewriteObjC::SynthSuperConstructorFunctionDecl() { 2352263508Sdim if (SuperConstructorFunctionDecl) 2353243791Sdim return; 2354243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super"); 2355243791Sdim SmallVector<QualType, 16> ArgTys; 2356243791Sdim QualType argT = Context->getObjCIdType(); 2357243791Sdim assert(!argT.isNull() && "Can't find 'id' type"); 2358243791Sdim ArgTys.push_back(argT); 2359243791Sdim ArgTys.push_back(argT); 2360243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2361249423Sdim ArgTys); 2362263508Sdim SuperConstructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2363249423Sdim SourceLocation(), 2364249423Sdim SourceLocation(), 2365249423Sdim msgSendIdent, msgSendType, 2366249423Sdim 0, SC_Extern); 2367243791Sdim} 2368243791Sdim 2369243791Sdim// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); 2370243791Sdimvoid RewriteObjC::SynthMsgSendFunctionDecl() { 2371243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend"); 2372243791Sdim SmallVector<QualType, 16> ArgTys; 2373243791Sdim QualType argT = Context->getObjCIdType(); 2374243791Sdim assert(!argT.isNull() && "Can't find 'id' type"); 2375243791Sdim ArgTys.push_back(argT); 2376243791Sdim argT = Context->getObjCSelType(); 2377243791Sdim assert(!argT.isNull() && "Can't find 'SEL' type"); 2378243791Sdim ArgTys.push_back(argT); 2379243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2380249423Sdim ArgTys, /*isVariadic=*/true); 2381243791Sdim MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2382249423Sdim SourceLocation(), 2383249423Sdim SourceLocation(), 2384249423Sdim msgSendIdent, msgSendType, 0, 2385249423Sdim SC_Extern); 2386243791Sdim} 2387243791Sdim 2388243791Sdim// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...); 2389243791Sdimvoid RewriteObjC::SynthMsgSendSuperFunctionDecl() { 2390243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); 2391243791Sdim SmallVector<QualType, 16> ArgTys; 2392243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2393243791Sdim SourceLocation(), SourceLocation(), 2394243791Sdim &Context->Idents.get("objc_super")); 2395243791Sdim QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 2396243791Sdim assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 2397243791Sdim ArgTys.push_back(argT); 2398243791Sdim argT = Context->getObjCSelType(); 2399243791Sdim assert(!argT.isNull() && "Can't find 'SEL' type"); 2400243791Sdim ArgTys.push_back(argT); 2401243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2402249423Sdim ArgTys, /*isVariadic=*/true); 2403243791Sdim MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2404249423Sdim SourceLocation(), 2405249423Sdim SourceLocation(), 2406249423Sdim msgSendIdent, msgSendType, 0, 2407249423Sdim SC_Extern); 2408243791Sdim} 2409243791Sdim 2410243791Sdim// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); 2411243791Sdimvoid RewriteObjC::SynthMsgSendStretFunctionDecl() { 2412243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret"); 2413243791Sdim SmallVector<QualType, 16> ArgTys; 2414243791Sdim QualType argT = Context->getObjCIdType(); 2415243791Sdim assert(!argT.isNull() && "Can't find 'id' type"); 2416243791Sdim ArgTys.push_back(argT); 2417243791Sdim argT = Context->getObjCSelType(); 2418243791Sdim assert(!argT.isNull() && "Can't find 'SEL' type"); 2419243791Sdim ArgTys.push_back(argT); 2420243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2421249423Sdim ArgTys, /*isVariadic=*/true); 2422243791Sdim MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2423249423Sdim SourceLocation(), 2424249423Sdim SourceLocation(), 2425249423Sdim msgSendIdent, msgSendType, 0, 2426249423Sdim SC_Extern); 2427243791Sdim} 2428243791Sdim 2429243791Sdim// SynthMsgSendSuperStretFunctionDecl - 2430243791Sdim// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...); 2431243791Sdimvoid RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { 2432243791Sdim IdentifierInfo *msgSendIdent = 2433243791Sdim &Context->Idents.get("objc_msgSendSuper_stret"); 2434243791Sdim SmallVector<QualType, 16> ArgTys; 2435243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2436243791Sdim SourceLocation(), SourceLocation(), 2437243791Sdim &Context->Idents.get("objc_super")); 2438243791Sdim QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 2439243791Sdim assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 2440243791Sdim ArgTys.push_back(argT); 2441243791Sdim argT = Context->getObjCSelType(); 2442243791Sdim assert(!argT.isNull() && "Can't find 'SEL' type"); 2443243791Sdim ArgTys.push_back(argT); 2444243791Sdim QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2445249423Sdim ArgTys, /*isVariadic=*/true); 2446243791Sdim MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2447243791Sdim SourceLocation(), 2448243791Sdim SourceLocation(), 2449249423Sdim msgSendIdent, 2450249423Sdim msgSendType, 0, 2451249423Sdim SC_Extern); 2452243791Sdim} 2453243791Sdim 2454243791Sdim// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); 2455243791Sdimvoid RewriteObjC::SynthMsgSendFpretFunctionDecl() { 2456243791Sdim IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret"); 2457243791Sdim SmallVector<QualType, 16> ArgTys; 2458243791Sdim QualType argT = Context->getObjCIdType(); 2459243791Sdim assert(!argT.isNull() && "Can't find 'id' type"); 2460243791Sdim ArgTys.push_back(argT); 2461243791Sdim argT = Context->getObjCSelType(); 2462243791Sdim assert(!argT.isNull() && "Can't find 'SEL' type"); 2463243791Sdim ArgTys.push_back(argT); 2464243791Sdim QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, 2465249423Sdim ArgTys, /*isVariadic=*/true); 2466243791Sdim MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2467249423Sdim SourceLocation(), 2468249423Sdim SourceLocation(), 2469249423Sdim msgSendIdent, msgSendType, 0, 2470249423Sdim SC_Extern); 2471243791Sdim} 2472243791Sdim 2473243791Sdim// SynthGetClassFunctionDecl - id objc_getClass(const char *name); 2474243791Sdimvoid RewriteObjC::SynthGetClassFunctionDecl() { 2475243791Sdim IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); 2476243791Sdim SmallVector<QualType, 16> ArgTys; 2477243791Sdim ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2478243791Sdim QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), 2479249423Sdim ArgTys); 2480243791Sdim GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2481249423Sdim SourceLocation(), 2482249423Sdim SourceLocation(), 2483249423Sdim getClassIdent, getClassType, 0, 2484249423Sdim SC_Extern); 2485243791Sdim} 2486243791Sdim 2487243791Sdim// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); 2488243791Sdimvoid RewriteObjC::SynthGetSuperClassFunctionDecl() { 2489243791Sdim IdentifierInfo *getSuperClassIdent = 2490243791Sdim &Context->Idents.get("class_getSuperclass"); 2491243791Sdim SmallVector<QualType, 16> ArgTys; 2492243791Sdim ArgTys.push_back(Context->getObjCClassType()); 2493243791Sdim QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 2494249423Sdim ArgTys); 2495243791Sdim GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2496243791Sdim SourceLocation(), 2497243791Sdim SourceLocation(), 2498243791Sdim getSuperClassIdent, 2499243791Sdim getClassType, 0, 2500249423Sdim SC_Extern); 2501243791Sdim} 2502243791Sdim 2503243791Sdim// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name); 2504243791Sdimvoid RewriteObjC::SynthGetMetaClassFunctionDecl() { 2505243791Sdim IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); 2506243791Sdim SmallVector<QualType, 16> ArgTys; 2507243791Sdim ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2508243791Sdim QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), 2509249423Sdim ArgTys); 2510243791Sdim GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 2511249423Sdim SourceLocation(), 2512249423Sdim SourceLocation(), 2513249423Sdim getClassIdent, getClassType, 2514249423Sdim 0, SC_Extern); 2515243791Sdim} 2516243791Sdim 2517243791SdimStmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { 2518243791Sdim QualType strType = getConstantStringStructType(); 2519243791Sdim 2520243791Sdim std::string S = "__NSConstantStringImpl_"; 2521243791Sdim 2522243791Sdim std::string tmpName = InFileName; 2523243791Sdim unsigned i; 2524243791Sdim for (i=0; i < tmpName.length(); i++) { 2525243791Sdim char c = tmpName.at(i); 2526243791Sdim // replace any non alphanumeric characters with '_'. 2527249423Sdim if (!isAlphanumeric(c)) 2528243791Sdim tmpName[i] = '_'; 2529243791Sdim } 2530243791Sdim S += tmpName; 2531243791Sdim S += "_"; 2532243791Sdim S += utostr(NumObjCStringLiterals++); 2533243791Sdim 2534243791Sdim Preamble += "static __NSConstantStringImpl " + S; 2535243791Sdim Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,"; 2536243791Sdim Preamble += "0x000007c8,"; // utf8_str 2537243791Sdim // The pretty printer for StringLiteral handles escape characters properly. 2538243791Sdim std::string prettyBufS; 2539243791Sdim llvm::raw_string_ostream prettyBuf(prettyBufS); 2540243791Sdim Exp->getString()->printPretty(prettyBuf, 0, PrintingPolicy(LangOpts)); 2541243791Sdim Preamble += prettyBuf.str(); 2542243791Sdim Preamble += ","; 2543243791Sdim Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; 2544243791Sdim 2545243791Sdim VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 2546243791Sdim SourceLocation(), &Context->Idents.get(S), 2547249423Sdim strType, 0, SC_Static); 2548243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue, 2549243791Sdim SourceLocation()); 2550243791Sdim Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, 2551243791Sdim Context->getPointerType(DRE->getType()), 2552243791Sdim VK_RValue, OK_Ordinary, 2553243791Sdim SourceLocation()); 2554243791Sdim // cast to NSConstantString * 2555243791Sdim CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), 2556243791Sdim CK_CPointerToObjCPointerCast, Unop); 2557243791Sdim ReplaceStmt(Exp, cast); 2558243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2559243791Sdim return cast; 2560243791Sdim} 2561243791Sdim 2562243791Sdim// struct objc_super { struct objc_object *receiver; struct objc_class *super; }; 2563243791SdimQualType RewriteObjC::getSuperStructType() { 2564243791Sdim if (!SuperStructDecl) { 2565243791Sdim SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2566243791Sdim SourceLocation(), SourceLocation(), 2567243791Sdim &Context->Idents.get("objc_super")); 2568243791Sdim QualType FieldTypes[2]; 2569243791Sdim 2570243791Sdim // struct objc_object *receiver; 2571243791Sdim FieldTypes[0] = Context->getObjCIdType(); 2572243791Sdim // struct objc_class *super; 2573243791Sdim FieldTypes[1] = Context->getObjCClassType(); 2574243791Sdim 2575243791Sdim // Create fields 2576243791Sdim for (unsigned i = 0; i < 2; ++i) { 2577243791Sdim SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, 2578243791Sdim SourceLocation(), 2579243791Sdim SourceLocation(), 0, 2580243791Sdim FieldTypes[i], 0, 2581243791Sdim /*BitWidth=*/0, 2582243791Sdim /*Mutable=*/false, 2583243791Sdim ICIS_NoInit)); 2584243791Sdim } 2585243791Sdim 2586243791Sdim SuperStructDecl->completeDefinition(); 2587243791Sdim } 2588243791Sdim return Context->getTagDeclType(SuperStructDecl); 2589243791Sdim} 2590243791Sdim 2591243791SdimQualType RewriteObjC::getConstantStringStructType() { 2592243791Sdim if (!ConstantStringDecl) { 2593243791Sdim ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2594243791Sdim SourceLocation(), SourceLocation(), 2595243791Sdim &Context->Idents.get("__NSConstantStringImpl")); 2596243791Sdim QualType FieldTypes[4]; 2597243791Sdim 2598243791Sdim // struct objc_object *receiver; 2599243791Sdim FieldTypes[0] = Context->getObjCIdType(); 2600243791Sdim // int flags; 2601243791Sdim FieldTypes[1] = Context->IntTy; 2602243791Sdim // char *str; 2603243791Sdim FieldTypes[2] = Context->getPointerType(Context->CharTy); 2604243791Sdim // long length; 2605243791Sdim FieldTypes[3] = Context->LongTy; 2606243791Sdim 2607243791Sdim // Create fields 2608243791Sdim for (unsigned i = 0; i < 4; ++i) { 2609243791Sdim ConstantStringDecl->addDecl(FieldDecl::Create(*Context, 2610243791Sdim ConstantStringDecl, 2611243791Sdim SourceLocation(), 2612243791Sdim SourceLocation(), 0, 2613243791Sdim FieldTypes[i], 0, 2614243791Sdim /*BitWidth=*/0, 2615243791Sdim /*Mutable=*/true, 2616243791Sdim ICIS_NoInit)); 2617243791Sdim } 2618243791Sdim 2619243791Sdim ConstantStringDecl->completeDefinition(); 2620243791Sdim } 2621243791Sdim return Context->getTagDeclType(ConstantStringDecl); 2622243791Sdim} 2623243791Sdim 2624243791SdimCallExpr *RewriteObjC::SynthMsgSendStretCallExpr(FunctionDecl *MsgSendStretFlavor, 2625243791Sdim QualType msgSendType, 2626243791Sdim QualType returnType, 2627243791Sdim SmallVectorImpl<QualType> &ArgTypes, 2628243791Sdim SmallVectorImpl<Expr*> &MsgExprs, 2629243791Sdim ObjCMethodDecl *Method) { 2630243791Sdim // Create a reference to the objc_msgSend_stret() declaration. 2631243791Sdim DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, 2632243791Sdim false, msgSendType, 2633243791Sdim VK_LValue, SourceLocation()); 2634243791Sdim // Need to cast objc_msgSend_stret to "void *" (see above comment). 2635243791Sdim CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, 2636243791Sdim Context->getPointerType(Context->VoidTy), 2637243791Sdim CK_BitCast, STDRE); 2638243791Sdim // Now do the "normal" pointer to function cast. 2639249423Sdim QualType castType = getSimpleFunctionType(returnType, ArgTypes, 2640249423Sdim Method ? Method->isVariadic() 2641249423Sdim : false); 2642243791Sdim castType = Context->getPointerType(castType); 2643243791Sdim cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 2644243791Sdim cast); 2645243791Sdim 2646243791Sdim // Don't forget the parens to enforce the proper binding. 2647243791Sdim ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); 2648243791Sdim 2649243791Sdim const FunctionType *FT = msgSendType->getAs<FunctionType>(); 2650243791Sdim CallExpr *STCE = new (Context) CallExpr(*Context, PE, MsgExprs, 2651243791Sdim FT->getResultType(), VK_RValue, 2652243791Sdim SourceLocation()); 2653243791Sdim return STCE; 2654243791Sdim 2655243791Sdim} 2656243791Sdim 2657243791Sdim 2658243791SdimStmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 2659243791Sdim SourceLocation StartLoc, 2660243791Sdim SourceLocation EndLoc) { 2661243791Sdim if (!SelGetUidFunctionDecl) 2662243791Sdim SynthSelGetUidFunctionDecl(); 2663243791Sdim if (!MsgSendFunctionDecl) 2664243791Sdim SynthMsgSendFunctionDecl(); 2665243791Sdim if (!MsgSendSuperFunctionDecl) 2666243791Sdim SynthMsgSendSuperFunctionDecl(); 2667243791Sdim if (!MsgSendStretFunctionDecl) 2668243791Sdim SynthMsgSendStretFunctionDecl(); 2669243791Sdim if (!MsgSendSuperStretFunctionDecl) 2670243791Sdim SynthMsgSendSuperStretFunctionDecl(); 2671243791Sdim if (!MsgSendFpretFunctionDecl) 2672243791Sdim SynthMsgSendFpretFunctionDecl(); 2673243791Sdim if (!GetClassFunctionDecl) 2674243791Sdim SynthGetClassFunctionDecl(); 2675243791Sdim if (!GetSuperClassFunctionDecl) 2676243791Sdim SynthGetSuperClassFunctionDecl(); 2677243791Sdim if (!GetMetaClassFunctionDecl) 2678243791Sdim SynthGetMetaClassFunctionDecl(); 2679243791Sdim 2680243791Sdim // default to objc_msgSend(). 2681243791Sdim FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 2682243791Sdim // May need to use objc_msgSend_stret() as well. 2683243791Sdim FunctionDecl *MsgSendStretFlavor = 0; 2684243791Sdim if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { 2685243791Sdim QualType resultType = mDecl->getResultType(); 2686243791Sdim if (resultType->isRecordType()) 2687243791Sdim MsgSendStretFlavor = MsgSendStretFunctionDecl; 2688243791Sdim else if (resultType->isRealFloatingType()) 2689243791Sdim MsgSendFlavor = MsgSendFpretFunctionDecl; 2690243791Sdim } 2691243791Sdim 2692243791Sdim // Synthesize a call to objc_msgSend(). 2693243791Sdim SmallVector<Expr*, 8> MsgExprs; 2694243791Sdim switch (Exp->getReceiverKind()) { 2695243791Sdim case ObjCMessageExpr::SuperClass: { 2696243791Sdim MsgSendFlavor = MsgSendSuperFunctionDecl; 2697243791Sdim if (MsgSendStretFlavor) 2698243791Sdim MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 2699243791Sdim assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 2700243791Sdim 2701243791Sdim ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 2702243791Sdim 2703243791Sdim SmallVector<Expr*, 4> InitExprs; 2704243791Sdim 2705243791Sdim // set the receiver to self, the first argument to all methods. 2706243791Sdim InitExprs.push_back( 2707243791Sdim NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2708243791Sdim CK_BitCast, 2709243791Sdim new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 2710243791Sdim false, 2711243791Sdim Context->getObjCIdType(), 2712243791Sdim VK_RValue, 2713243791Sdim SourceLocation())) 2714243791Sdim ); // set the 'receiver'. 2715243791Sdim 2716243791Sdim // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 2717243791Sdim SmallVector<Expr*, 8> ClsExprs; 2718243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2719243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 2720243791Sdim ClassDecl->getIdentifier()->getName(), 2721243791Sdim StringLiteral::Ascii, false, 2722243791Sdim argType, SourceLocation())); 2723243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, 2724243791Sdim &ClsExprs[0], 2725243791Sdim ClsExprs.size(), 2726243791Sdim StartLoc, 2727243791Sdim EndLoc); 2728243791Sdim // (Class)objc_getClass("CurrentClass") 2729243791Sdim CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 2730243791Sdim Context->getObjCClassType(), 2731243791Sdim CK_BitCast, Cls); 2732243791Sdim ClsExprs.clear(); 2733243791Sdim ClsExprs.push_back(ArgExpr); 2734243791Sdim Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 2735243791Sdim &ClsExprs[0], ClsExprs.size(), 2736243791Sdim StartLoc, EndLoc); 2737243791Sdim 2738243791Sdim // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 2739243791Sdim // To turn off a warning, type-cast to 'id' 2740243791Sdim InitExprs.push_back( // set 'super class', using class_getSuperclass(). 2741243791Sdim NoTypeInfoCStyleCastExpr(Context, 2742243791Sdim Context->getObjCIdType(), 2743243791Sdim CK_BitCast, Cls)); 2744243791Sdim // struct objc_super 2745243791Sdim QualType superType = getSuperStructType(); 2746243791Sdim Expr *SuperRep; 2747243791Sdim 2748243791Sdim if (LangOpts.MicrosoftExt) { 2749263508Sdim SynthSuperConstructorFunctionDecl(); 2750263508Sdim // Simulate a constructor call... 2751263508Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl, 2752243791Sdim false, superType, VK_LValue, 2753243791Sdim SourceLocation()); 2754243791Sdim SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs, 2755243791Sdim superType, VK_LValue, 2756243791Sdim SourceLocation()); 2757243791Sdim // The code for super is a little tricky to prevent collision with 2758243791Sdim // the structure definition in the header. The rewriter has it's own 2759243791Sdim // internal definition (__rw_objc_super) that is uses. This is why 2760243791Sdim // we need the cast below. For example: 2761243791Sdim // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 2762243791Sdim // 2763243791Sdim SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 2764243791Sdim Context->getPointerType(SuperRep->getType()), 2765243791Sdim VK_RValue, OK_Ordinary, 2766243791Sdim SourceLocation()); 2767243791Sdim SuperRep = NoTypeInfoCStyleCastExpr(Context, 2768243791Sdim Context->getPointerType(superType), 2769243791Sdim CK_BitCast, SuperRep); 2770243791Sdim } else { 2771243791Sdim // (struct objc_super) { <exprs from above> } 2772243791Sdim InitListExpr *ILE = 2773243791Sdim new (Context) InitListExpr(*Context, SourceLocation(), InitExprs, 2774243791Sdim SourceLocation()); 2775243791Sdim TypeSourceInfo *superTInfo 2776243791Sdim = Context->getTrivialTypeSourceInfo(superType); 2777243791Sdim SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 2778243791Sdim superType, VK_LValue, 2779243791Sdim ILE, false); 2780243791Sdim // struct objc_super * 2781243791Sdim SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 2782243791Sdim Context->getPointerType(SuperRep->getType()), 2783243791Sdim VK_RValue, OK_Ordinary, 2784243791Sdim SourceLocation()); 2785243791Sdim } 2786243791Sdim MsgExprs.push_back(SuperRep); 2787243791Sdim break; 2788243791Sdim } 2789243791Sdim 2790243791Sdim case ObjCMessageExpr::Class: { 2791243791Sdim SmallVector<Expr*, 8> ClsExprs; 2792243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2793243791Sdim ObjCInterfaceDecl *Class 2794243791Sdim = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface(); 2795243791Sdim IdentifierInfo *clsName = Class->getIdentifier(); 2796243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 2797243791Sdim clsName->getName(), 2798243791Sdim StringLiteral::Ascii, false, 2799243791Sdim argType, SourceLocation())); 2800243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 2801243791Sdim &ClsExprs[0], 2802243791Sdim ClsExprs.size(), 2803243791Sdim StartLoc, EndLoc); 2804243791Sdim MsgExprs.push_back(Cls); 2805243791Sdim break; 2806243791Sdim } 2807243791Sdim 2808243791Sdim case ObjCMessageExpr::SuperInstance:{ 2809243791Sdim MsgSendFlavor = MsgSendSuperFunctionDecl; 2810243791Sdim if (MsgSendStretFlavor) 2811243791Sdim MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 2812243791Sdim assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 2813243791Sdim ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 2814243791Sdim SmallVector<Expr*, 4> InitExprs; 2815243791Sdim 2816243791Sdim InitExprs.push_back( 2817243791Sdim NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2818243791Sdim CK_BitCast, 2819243791Sdim new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 2820243791Sdim false, 2821243791Sdim Context->getObjCIdType(), 2822243791Sdim VK_RValue, SourceLocation())) 2823243791Sdim ); // set the 'receiver'. 2824243791Sdim 2825243791Sdim // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 2826243791Sdim SmallVector<Expr*, 8> ClsExprs; 2827243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2828243791Sdim ClsExprs.push_back(StringLiteral::Create(*Context, 2829243791Sdim ClassDecl->getIdentifier()->getName(), 2830243791Sdim StringLiteral::Ascii, false, argType, 2831243791Sdim SourceLocation())); 2832243791Sdim CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 2833243791Sdim &ClsExprs[0], 2834243791Sdim ClsExprs.size(), 2835243791Sdim StartLoc, EndLoc); 2836243791Sdim // (Class)objc_getClass("CurrentClass") 2837243791Sdim CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 2838243791Sdim Context->getObjCClassType(), 2839243791Sdim CK_BitCast, Cls); 2840243791Sdim ClsExprs.clear(); 2841243791Sdim ClsExprs.push_back(ArgExpr); 2842243791Sdim Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 2843243791Sdim &ClsExprs[0], ClsExprs.size(), 2844243791Sdim StartLoc, EndLoc); 2845243791Sdim 2846243791Sdim // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 2847243791Sdim // To turn off a warning, type-cast to 'id' 2848243791Sdim InitExprs.push_back( 2849243791Sdim // set 'super class', using class_getSuperclass(). 2850243791Sdim NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2851243791Sdim CK_BitCast, Cls)); 2852243791Sdim // struct objc_super 2853243791Sdim QualType superType = getSuperStructType(); 2854243791Sdim Expr *SuperRep; 2855243791Sdim 2856243791Sdim if (LangOpts.MicrosoftExt) { 2857263508Sdim SynthSuperConstructorFunctionDecl(); 2858263508Sdim // Simulate a constructor call... 2859263508Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperConstructorFunctionDecl, 2860243791Sdim false, superType, VK_LValue, 2861243791Sdim SourceLocation()); 2862243791Sdim SuperRep = new (Context) CallExpr(*Context, DRE, InitExprs, 2863243791Sdim superType, VK_LValue, SourceLocation()); 2864243791Sdim // The code for super is a little tricky to prevent collision with 2865243791Sdim // the structure definition in the header. The rewriter has it's own 2866243791Sdim // internal definition (__rw_objc_super) that is uses. This is why 2867243791Sdim // we need the cast below. For example: 2868243791Sdim // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 2869243791Sdim // 2870243791Sdim SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 2871243791Sdim Context->getPointerType(SuperRep->getType()), 2872243791Sdim VK_RValue, OK_Ordinary, 2873243791Sdim SourceLocation()); 2874243791Sdim SuperRep = NoTypeInfoCStyleCastExpr(Context, 2875243791Sdim Context->getPointerType(superType), 2876243791Sdim CK_BitCast, SuperRep); 2877243791Sdim } else { 2878243791Sdim // (struct objc_super) { <exprs from above> } 2879243791Sdim InitListExpr *ILE = 2880243791Sdim new (Context) InitListExpr(*Context, SourceLocation(), InitExprs, 2881243791Sdim SourceLocation()); 2882243791Sdim TypeSourceInfo *superTInfo 2883243791Sdim = Context->getTrivialTypeSourceInfo(superType); 2884243791Sdim SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 2885243791Sdim superType, VK_RValue, ILE, 2886243791Sdim false); 2887243791Sdim } 2888243791Sdim MsgExprs.push_back(SuperRep); 2889243791Sdim break; 2890243791Sdim } 2891243791Sdim 2892243791Sdim case ObjCMessageExpr::Instance: { 2893243791Sdim // Remove all type-casts because it may contain objc-style types; e.g. 2894243791Sdim // Foo<Proto> *. 2895243791Sdim Expr *recExpr = Exp->getInstanceReceiver(); 2896243791Sdim while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) 2897243791Sdim recExpr = CE->getSubExpr(); 2898243791Sdim CastKind CK = recExpr->getType()->isObjCObjectPointerType() 2899243791Sdim ? CK_BitCast : recExpr->getType()->isBlockPointerType() 2900243791Sdim ? CK_BlockPointerToObjCPointerCast 2901243791Sdim : CK_CPointerToObjCPointerCast; 2902243791Sdim 2903243791Sdim recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2904243791Sdim CK, recExpr); 2905243791Sdim MsgExprs.push_back(recExpr); 2906243791Sdim break; 2907243791Sdim } 2908243791Sdim } 2909243791Sdim 2910243791Sdim // Create a call to sel_registerName("selName"), it will be the 2nd argument. 2911243791Sdim SmallVector<Expr*, 8> SelExprs; 2912243791Sdim QualType argType = Context->getPointerType(Context->CharTy); 2913243791Sdim SelExprs.push_back(StringLiteral::Create(*Context, 2914243791Sdim Exp->getSelector().getAsString(), 2915243791Sdim StringLiteral::Ascii, false, 2916243791Sdim argType, SourceLocation())); 2917243791Sdim CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 2918243791Sdim &SelExprs[0], SelExprs.size(), 2919243791Sdim StartLoc, 2920243791Sdim EndLoc); 2921243791Sdim MsgExprs.push_back(SelExp); 2922243791Sdim 2923243791Sdim // Now push any user supplied arguments. 2924243791Sdim for (unsigned i = 0; i < Exp->getNumArgs(); i++) { 2925243791Sdim Expr *userExpr = Exp->getArg(i); 2926243791Sdim // Make all implicit casts explicit...ICE comes in handy:-) 2927243791Sdim if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { 2928243791Sdim // Reuse the ICE type, it is exactly what the doctor ordered. 2929243791Sdim QualType type = ICE->getType(); 2930243791Sdim if (needToScanForQualifiers(type)) 2931243791Sdim type = Context->getObjCIdType(); 2932243791Sdim // Make sure we convert "type (^)(...)" to "type (*)(...)". 2933243791Sdim (void)convertBlockPointerToFunctionPointer(type); 2934243791Sdim const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 2935243791Sdim CastKind CK; 2936243791Sdim if (SubExpr->getType()->isIntegralType(*Context) && 2937243791Sdim type->isBooleanType()) { 2938243791Sdim CK = CK_IntegralToBoolean; 2939243791Sdim } else if (type->isObjCObjectPointerType()) { 2940243791Sdim if (SubExpr->getType()->isBlockPointerType()) { 2941243791Sdim CK = CK_BlockPointerToObjCPointerCast; 2942243791Sdim } else if (SubExpr->getType()->isPointerType()) { 2943243791Sdim CK = CK_CPointerToObjCPointerCast; 2944243791Sdim } else { 2945243791Sdim CK = CK_BitCast; 2946243791Sdim } 2947243791Sdim } else { 2948243791Sdim CK = CK_BitCast; 2949243791Sdim } 2950243791Sdim 2951243791Sdim userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); 2952243791Sdim } 2953243791Sdim // Make id<P...> cast into an 'id' cast. 2954243791Sdim else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { 2955243791Sdim if (CE->getType()->isObjCQualifiedIdType()) { 2956243791Sdim while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) 2957243791Sdim userExpr = CE->getSubExpr(); 2958243791Sdim CastKind CK; 2959243791Sdim if (userExpr->getType()->isIntegralType(*Context)) { 2960243791Sdim CK = CK_IntegralToPointer; 2961243791Sdim } else if (userExpr->getType()->isBlockPointerType()) { 2962243791Sdim CK = CK_BlockPointerToObjCPointerCast; 2963243791Sdim } else if (userExpr->getType()->isPointerType()) { 2964243791Sdim CK = CK_CPointerToObjCPointerCast; 2965243791Sdim } else { 2966243791Sdim CK = CK_BitCast; 2967243791Sdim } 2968243791Sdim userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2969243791Sdim CK, userExpr); 2970243791Sdim } 2971243791Sdim } 2972243791Sdim MsgExprs.push_back(userExpr); 2973243791Sdim // We've transferred the ownership to MsgExprs. For now, we *don't* null 2974243791Sdim // out the argument in the original expression (since we aren't deleting 2975243791Sdim // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info. 2976243791Sdim //Exp->setArg(i, 0); 2977243791Sdim } 2978243791Sdim // Generate the funky cast. 2979243791Sdim CastExpr *cast; 2980243791Sdim SmallVector<QualType, 8> ArgTypes; 2981243791Sdim QualType returnType; 2982243791Sdim 2983243791Sdim // Push 'id' and 'SEL', the 2 implicit arguments. 2984243791Sdim if (MsgSendFlavor == MsgSendSuperFunctionDecl) 2985243791Sdim ArgTypes.push_back(Context->getPointerType(getSuperStructType())); 2986243791Sdim else 2987243791Sdim ArgTypes.push_back(Context->getObjCIdType()); 2988243791Sdim ArgTypes.push_back(Context->getObjCSelType()); 2989243791Sdim if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { 2990243791Sdim // Push any user argument types. 2991243791Sdim for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 2992243791Sdim E = OMD->param_end(); PI != E; ++PI) { 2993243791Sdim QualType t = (*PI)->getType()->isObjCQualifiedIdType() 2994243791Sdim ? Context->getObjCIdType() 2995243791Sdim : (*PI)->getType(); 2996243791Sdim // Make sure we convert "t (^)(...)" to "t (*)(...)". 2997243791Sdim (void)convertBlockPointerToFunctionPointer(t); 2998243791Sdim ArgTypes.push_back(t); 2999243791Sdim } 3000243791Sdim returnType = Exp->getType(); 3001243791Sdim convertToUnqualifiedObjCType(returnType); 3002243791Sdim (void)convertBlockPointerToFunctionPointer(returnType); 3003243791Sdim } else { 3004243791Sdim returnType = Context->getObjCIdType(); 3005243791Sdim } 3006243791Sdim // Get the type, we will need to reference it in a couple spots. 3007243791Sdim QualType msgSendType = MsgSendFlavor->getType(); 3008243791Sdim 3009243791Sdim // Create a reference to the objc_msgSend() declaration. 3010243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 3011243791Sdim VK_LValue, SourceLocation()); 3012243791Sdim 3013243791Sdim // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 3014243791Sdim // If we don't do this cast, we get the following bizarre warning/note: 3015243791Sdim // xx.m:13: warning: function called through a non-compatible type 3016243791Sdim // xx.m:13: note: if this code is reached, the program will abort 3017243791Sdim cast = NoTypeInfoCStyleCastExpr(Context, 3018243791Sdim Context->getPointerType(Context->VoidTy), 3019243791Sdim CK_BitCast, DRE); 3020243791Sdim 3021243791Sdim // Now do the "normal" pointer to function cast. 3022249423Sdim // If we don't have a method decl, force a variadic cast. 3023249423Sdim const ObjCMethodDecl *MD = Exp->getMethodDecl(); 3024243791Sdim QualType castType = 3025249423Sdim getSimpleFunctionType(returnType, ArgTypes, MD ? MD->isVariadic() : true); 3026243791Sdim castType = Context->getPointerType(castType); 3027243791Sdim cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 3028243791Sdim cast); 3029243791Sdim 3030243791Sdim // Don't forget the parens to enforce the proper binding. 3031243791Sdim ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 3032243791Sdim 3033243791Sdim const FunctionType *FT = msgSendType->getAs<FunctionType>(); 3034243791Sdim CallExpr *CE = new (Context) CallExpr(*Context, PE, MsgExprs, 3035243791Sdim FT->getResultType(), VK_RValue, 3036243791Sdim EndLoc); 3037243791Sdim Stmt *ReplacingStmt = CE; 3038243791Sdim if (MsgSendStretFlavor) { 3039243791Sdim // We have the method which returns a struct/union. Must also generate 3040243791Sdim // call to objc_msgSend_stret and hang both varieties on a conditional 3041243791Sdim // expression which dictate which one to envoke depending on size of 3042243791Sdim // method's return type. 3043243791Sdim 3044243791Sdim CallExpr *STCE = SynthMsgSendStretCallExpr(MsgSendStretFlavor, 3045243791Sdim msgSendType, returnType, 3046243791Sdim ArgTypes, MsgExprs, 3047243791Sdim Exp->getMethodDecl()); 3048243791Sdim 3049243791Sdim // Build sizeof(returnType) 3050243791Sdim UnaryExprOrTypeTraitExpr *sizeofExpr = 3051243791Sdim new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf, 3052243791Sdim Context->getTrivialTypeSourceInfo(returnType), 3053243791Sdim Context->getSizeType(), SourceLocation(), 3054243791Sdim SourceLocation()); 3055243791Sdim // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 3056243791Sdim // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. 3057243791Sdim // For X86 it is more complicated and some kind of target specific routine 3058243791Sdim // is needed to decide what to do. 3059243791Sdim unsigned IntSize = 3060243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 3061243791Sdim IntegerLiteral *limit = IntegerLiteral::Create(*Context, 3062243791Sdim llvm::APInt(IntSize, 8), 3063243791Sdim Context->IntTy, 3064243791Sdim SourceLocation()); 3065243791Sdim BinaryOperator *lessThanExpr = 3066243791Sdim new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, 3067243791Sdim VK_RValue, OK_Ordinary, SourceLocation(), 3068243791Sdim false); 3069243791Sdim // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 3070243791Sdim ConditionalOperator *CondExpr = 3071243791Sdim new (Context) ConditionalOperator(lessThanExpr, 3072243791Sdim SourceLocation(), CE, 3073243791Sdim SourceLocation(), STCE, 3074243791Sdim returnType, VK_RValue, OK_Ordinary); 3075243791Sdim ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 3076243791Sdim CondExpr); 3077243791Sdim } 3078243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 3079243791Sdim return ReplacingStmt; 3080243791Sdim} 3081243791Sdim 3082243791SdimStmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { 3083243791Sdim Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(), 3084243791Sdim Exp->getLocEnd()); 3085243791Sdim 3086243791Sdim // Now do the actual rewrite. 3087243791Sdim ReplaceStmt(Exp, ReplacingStmt); 3088243791Sdim 3089243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 3090243791Sdim return ReplacingStmt; 3091243791Sdim} 3092243791Sdim 3093243791Sdim// typedef struct objc_object Protocol; 3094243791SdimQualType RewriteObjC::getProtocolType() { 3095243791Sdim if (!ProtocolTypeDecl) { 3096243791Sdim TypeSourceInfo *TInfo 3097243791Sdim = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); 3098243791Sdim ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, 3099243791Sdim SourceLocation(), SourceLocation(), 3100243791Sdim &Context->Idents.get("Protocol"), 3101243791Sdim TInfo); 3102243791Sdim } 3103243791Sdim return Context->getTypeDeclType(ProtocolTypeDecl); 3104243791Sdim} 3105243791Sdim 3106243791Sdim/// RewriteObjCProtocolExpr - Rewrite a protocol expression into 3107243791Sdim/// a synthesized/forward data reference (to the protocol's metadata). 3108243791Sdim/// The forward references (and metadata) are generated in 3109243791Sdim/// RewriteObjC::HandleTranslationUnit(). 3110243791SdimStmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { 3111243791Sdim std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); 3112243791Sdim IdentifierInfo *ID = &Context->Idents.get(Name); 3113243791Sdim VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 3114243791Sdim SourceLocation(), ID, getProtocolType(), 0, 3115249423Sdim SC_Extern); 3116243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(), 3117243791Sdim VK_LValue, SourceLocation()); 3118243791Sdim Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, 3119243791Sdim Context->getPointerType(DRE->getType()), 3120243791Sdim VK_RValue, OK_Ordinary, SourceLocation()); 3121243791Sdim CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), 3122243791Sdim CK_BitCast, 3123243791Sdim DerefExpr); 3124243791Sdim ReplaceStmt(Exp, castExpr); 3125243791Sdim ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl()); 3126243791Sdim // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 3127243791Sdim return castExpr; 3128243791Sdim 3129243791Sdim} 3130243791Sdim 3131243791Sdimbool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, 3132243791Sdim const char *endBuf) { 3133243791Sdim while (startBuf < endBuf) { 3134243791Sdim if (*startBuf == '#') { 3135243791Sdim // Skip whitespace. 3136243791Sdim for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf) 3137243791Sdim ; 3138243791Sdim if (!strncmp(startBuf, "if", strlen("if")) || 3139243791Sdim !strncmp(startBuf, "ifdef", strlen("ifdef")) || 3140243791Sdim !strncmp(startBuf, "ifndef", strlen("ifndef")) || 3141243791Sdim !strncmp(startBuf, "define", strlen("define")) || 3142243791Sdim !strncmp(startBuf, "undef", strlen("undef")) || 3143243791Sdim !strncmp(startBuf, "else", strlen("else")) || 3144243791Sdim !strncmp(startBuf, "elif", strlen("elif")) || 3145243791Sdim !strncmp(startBuf, "endif", strlen("endif")) || 3146243791Sdim !strncmp(startBuf, "pragma", strlen("pragma")) || 3147243791Sdim !strncmp(startBuf, "include", strlen("include")) || 3148243791Sdim !strncmp(startBuf, "import", strlen("import")) || 3149243791Sdim !strncmp(startBuf, "include_next", strlen("include_next"))) 3150243791Sdim return true; 3151243791Sdim } 3152243791Sdim startBuf++; 3153243791Sdim } 3154243791Sdim return false; 3155243791Sdim} 3156243791Sdim 3157243791Sdim/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to 3158243791Sdim/// an objective-c class with ivars. 3159243791Sdimvoid RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 3160243791Sdim std::string &Result) { 3161243791Sdim assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); 3162243791Sdim assert(CDecl->getName() != "" && 3163243791Sdim "Name missing in SynthesizeObjCInternalStruct"); 3164243791Sdim // Do not synthesize more than once. 3165243791Sdim if (ObjCSynthesizedStructs.count(CDecl)) 3166243791Sdim return; 3167243791Sdim ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); 3168243791Sdim int NumIvars = CDecl->ivar_size(); 3169243791Sdim SourceLocation LocStart = CDecl->getLocStart(); 3170243791Sdim SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc(); 3171243791Sdim 3172243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 3173243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 3174243791Sdim 3175243791Sdim // If no ivars and no root or if its root, directly or indirectly, 3176243791Sdim // have no ivars (thus not synthesized) then no need to synthesize this class. 3177243791Sdim if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) && 3178243791Sdim (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { 3179243791Sdim endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 3180243791Sdim ReplaceText(LocStart, endBuf-startBuf, Result); 3181243791Sdim return; 3182243791Sdim } 3183243791Sdim 3184243791Sdim // FIXME: This has potential of causing problem. If 3185243791Sdim // SynthesizeObjCInternalStruct is ever called recursively. 3186243791Sdim Result += "\nstruct "; 3187243791Sdim Result += CDecl->getNameAsString(); 3188243791Sdim if (LangOpts.MicrosoftExt) 3189243791Sdim Result += "_IMPL"; 3190243791Sdim 3191243791Sdim if (NumIvars > 0) { 3192243791Sdim const char *cursor = strchr(startBuf, '{'); 3193243791Sdim assert((cursor && endBuf) 3194243791Sdim && "SynthesizeObjCInternalStruct - malformed @interface"); 3195243791Sdim // If the buffer contains preprocessor directives, we do more fine-grained 3196243791Sdim // rewrites. This is intended to fix code that looks like (which occurs in 3197243791Sdim // NSURL.h, for example): 3198243791Sdim // 3199243791Sdim // #ifdef XYZ 3200243791Sdim // @interface Foo : NSObject 3201243791Sdim // #else 3202243791Sdim // @interface FooBar : NSObject 3203243791Sdim // #endif 3204243791Sdim // { 3205243791Sdim // int i; 3206243791Sdim // } 3207243791Sdim // @end 3208243791Sdim // 3209243791Sdim // This clause is segregated to avoid breaking the common case. 3210243791Sdim if (BufferContainsPPDirectives(startBuf, cursor)) { 3211243791Sdim SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() : 3212243791Sdim CDecl->getAtStartLoc(); 3213243791Sdim const char *endHeader = SM->getCharacterData(L); 3214243791Sdim endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts); 3215243791Sdim 3216243791Sdim if (CDecl->protocol_begin() != CDecl->protocol_end()) { 3217243791Sdim // advance to the end of the referenced protocols. 3218243791Sdim while (endHeader < cursor && *endHeader != '>') endHeader++; 3219243791Sdim endHeader++; 3220243791Sdim } 3221243791Sdim // rewrite the original header 3222243791Sdim ReplaceText(LocStart, endHeader-startBuf, Result); 3223243791Sdim } else { 3224243791Sdim // rewrite the original header *without* disturbing the '{' 3225243791Sdim ReplaceText(LocStart, cursor-startBuf, Result); 3226243791Sdim } 3227243791Sdim if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 3228243791Sdim Result = "\n struct "; 3229243791Sdim Result += RCDecl->getNameAsString(); 3230243791Sdim Result += "_IMPL "; 3231243791Sdim Result += RCDecl->getNameAsString(); 3232243791Sdim Result += "_IVARS;\n"; 3233243791Sdim 3234243791Sdim // insert the super class structure definition. 3235243791Sdim SourceLocation OnePastCurly = 3236243791Sdim LocStart.getLocWithOffset(cursor-startBuf+1); 3237243791Sdim InsertText(OnePastCurly, Result); 3238243791Sdim } 3239243791Sdim cursor++; // past '{' 3240243791Sdim 3241243791Sdim // Now comment out any visibility specifiers. 3242243791Sdim while (cursor < endBuf) { 3243243791Sdim if (*cursor == '@') { 3244243791Sdim SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3245243791Sdim // Skip whitespace. 3246243791Sdim for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor) 3247243791Sdim /*scan*/; 3248243791Sdim 3249243791Sdim // FIXME: presence of @public, etc. inside comment results in 3250243791Sdim // this transformation as well, which is still correct c-code. 3251243791Sdim if (!strncmp(cursor, "public", strlen("public")) || 3252243791Sdim !strncmp(cursor, "private", strlen("private")) || 3253243791Sdim !strncmp(cursor, "package", strlen("package")) || 3254243791Sdim !strncmp(cursor, "protected", strlen("protected"))) 3255243791Sdim InsertText(atLoc, "// "); 3256243791Sdim } 3257243791Sdim // FIXME: If there are cases where '<' is used in ivar declaration part 3258243791Sdim // of user code, then scan the ivar list and use needToScanForQualifiers 3259243791Sdim // for type checking. 3260243791Sdim else if (*cursor == '<') { 3261243791Sdim SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3262243791Sdim InsertText(atLoc, "/* "); 3263243791Sdim cursor = strchr(cursor, '>'); 3264243791Sdim cursor++; 3265243791Sdim atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3266243791Sdim InsertText(atLoc, " */"); 3267243791Sdim } else if (*cursor == '^') { // rewrite block specifier. 3268243791Sdim SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf); 3269243791Sdim ReplaceText(caretLoc, 1, "*"); 3270243791Sdim } 3271243791Sdim cursor++; 3272243791Sdim } 3273243791Sdim // Don't forget to add a ';'!! 3274243791Sdim InsertText(LocEnd.getLocWithOffset(1), ";"); 3275243791Sdim } else { // we don't have any instance variables - insert super struct. 3276243791Sdim endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 3277243791Sdim Result += " {\n struct "; 3278243791Sdim Result += RCDecl->getNameAsString(); 3279243791Sdim Result += "_IMPL "; 3280243791Sdim Result += RCDecl->getNameAsString(); 3281243791Sdim Result += "_IVARS;\n};\n"; 3282243791Sdim ReplaceText(LocStart, endBuf-startBuf, Result); 3283243791Sdim } 3284243791Sdim // Mark this struct as having been generated. 3285243791Sdim if (!ObjCSynthesizedStructs.insert(CDecl)) 3286243791Sdim llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct"); 3287243791Sdim} 3288243791Sdim 3289243791Sdim//===----------------------------------------------------------------------===// 3290243791Sdim// Meta Data Emission 3291243791Sdim//===----------------------------------------------------------------------===// 3292243791Sdim 3293243791Sdim 3294243791Sdim/// RewriteImplementations - This routine rewrites all method implementations 3295243791Sdim/// and emits meta-data. 3296243791Sdim 3297243791Sdimvoid RewriteObjC::RewriteImplementations() { 3298243791Sdim int ClsDefCount = ClassImplementation.size(); 3299243791Sdim int CatDefCount = CategoryImplementation.size(); 3300243791Sdim 3301243791Sdim // Rewrite implemented methods 3302243791Sdim for (int i = 0; i < ClsDefCount; i++) 3303243791Sdim RewriteImplementationDecl(ClassImplementation[i]); 3304243791Sdim 3305243791Sdim for (int i = 0; i < CatDefCount; i++) 3306243791Sdim RewriteImplementationDecl(CategoryImplementation[i]); 3307243791Sdim} 3308243791Sdim 3309243791Sdimvoid RewriteObjC::RewriteByRefString(std::string &ResultStr, 3310243791Sdim const std::string &Name, 3311243791Sdim ValueDecl *VD, bool def) { 3312243791Sdim assert(BlockByRefDeclNo.count(VD) && 3313243791Sdim "RewriteByRefString: ByRef decl missing"); 3314243791Sdim if (def) 3315243791Sdim ResultStr += "struct "; 3316243791Sdim ResultStr += "__Block_byref_" + Name + 3317243791Sdim "_" + utostr(BlockByRefDeclNo[VD]) ; 3318243791Sdim} 3319243791Sdim 3320243791Sdimstatic bool HasLocalVariableExternalStorage(ValueDecl *VD) { 3321243791Sdim if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 3322243791Sdim return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage()); 3323243791Sdim return false; 3324243791Sdim} 3325243791Sdim 3326243791Sdimstd::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, 3327243791Sdim StringRef funcName, 3328243791Sdim std::string Tag) { 3329243791Sdim const FunctionType *AFT = CE->getFunctionType(); 3330243791Sdim QualType RT = AFT->getResultType(); 3331243791Sdim std::string StructRef = "struct " + Tag; 3332243791Sdim std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" + 3333243791Sdim funcName.str() + "_" + "block_func_" + utostr(i); 3334243791Sdim 3335243791Sdim BlockDecl *BD = CE->getBlockDecl(); 3336243791Sdim 3337243791Sdim if (isa<FunctionNoProtoType>(AFT)) { 3338243791Sdim // No user-supplied arguments. Still need to pass in a pointer to the 3339243791Sdim // block (to reference imported block decl refs). 3340243791Sdim S += "(" + StructRef + " *__cself)"; 3341243791Sdim } else if (BD->param_empty()) { 3342243791Sdim S += "(" + StructRef + " *__cself)"; 3343243791Sdim } else { 3344243791Sdim const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); 3345243791Sdim assert(FT && "SynthesizeBlockFunc: No function proto"); 3346243791Sdim S += '('; 3347243791Sdim // first add the implicit argument. 3348243791Sdim S += StructRef + " *__cself, "; 3349243791Sdim std::string ParamStr; 3350243791Sdim for (BlockDecl::param_iterator AI = BD->param_begin(), 3351243791Sdim E = BD->param_end(); AI != E; ++AI) { 3352243791Sdim if (AI != BD->param_begin()) S += ", "; 3353243791Sdim ParamStr = (*AI)->getNameAsString(); 3354243791Sdim QualType QT = (*AI)->getType(); 3355243791Sdim (void)convertBlockPointerToFunctionPointer(QT); 3356243791Sdim QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); 3357243791Sdim S += ParamStr; 3358243791Sdim } 3359243791Sdim if (FT->isVariadic()) { 3360243791Sdim if (!BD->param_empty()) S += ", "; 3361243791Sdim S += "..."; 3362243791Sdim } 3363243791Sdim S += ')'; 3364243791Sdim } 3365243791Sdim S += " {\n"; 3366243791Sdim 3367243791Sdim // Create local declarations to avoid rewriting all closure decl ref exprs. 3368243791Sdim // First, emit a declaration for all "by ref" decls. 3369263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 3370243791Sdim E = BlockByRefDecls.end(); I != E; ++I) { 3371243791Sdim S += " "; 3372243791Sdim std::string Name = (*I)->getNameAsString(); 3373243791Sdim std::string TypeString; 3374243791Sdim RewriteByRefString(TypeString, Name, (*I)); 3375243791Sdim TypeString += " *"; 3376243791Sdim Name = TypeString + Name; 3377243791Sdim S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; 3378243791Sdim } 3379243791Sdim // Next, emit a declaration for all "by copy" declarations. 3380263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 3381243791Sdim E = BlockByCopyDecls.end(); I != E; ++I) { 3382243791Sdim S += " "; 3383243791Sdim // Handle nested closure invocation. For example: 3384243791Sdim // 3385243791Sdim // void (^myImportedClosure)(void); 3386243791Sdim // myImportedClosure = ^(void) { setGlobalInt(x + y); }; 3387243791Sdim // 3388243791Sdim // void (^anotherClosure)(void); 3389243791Sdim // anotherClosure = ^(void) { 3390243791Sdim // myImportedClosure(); // import and invoke the closure 3391243791Sdim // }; 3392243791Sdim // 3393243791Sdim if (isTopLevelBlockPointerType((*I)->getType())) { 3394243791Sdim RewriteBlockPointerTypeVariable(S, (*I)); 3395243791Sdim S += " = ("; 3396243791Sdim RewriteBlockPointerType(S, (*I)->getType()); 3397243791Sdim S += ")"; 3398243791Sdim S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n"; 3399243791Sdim } 3400243791Sdim else { 3401243791Sdim std::string Name = (*I)->getNameAsString(); 3402243791Sdim QualType QT = (*I)->getType(); 3403243791Sdim if (HasLocalVariableExternalStorage(*I)) 3404243791Sdim QT = Context->getPointerType(QT); 3405243791Sdim QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 3406243791Sdim S += Name + " = __cself->" + 3407243791Sdim (*I)->getNameAsString() + "; // bound by copy\n"; 3408243791Sdim } 3409243791Sdim } 3410243791Sdim std::string RewrittenStr = RewrittenBlockExprs[CE]; 3411243791Sdim const char *cstr = RewrittenStr.c_str(); 3412243791Sdim while (*cstr++ != '{') ; 3413243791Sdim S += cstr; 3414243791Sdim S += "\n"; 3415243791Sdim return S; 3416243791Sdim} 3417243791Sdim 3418243791Sdimstd::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 3419243791Sdim StringRef funcName, 3420243791Sdim std::string Tag) { 3421243791Sdim std::string StructRef = "struct " + Tag; 3422243791Sdim std::string S = "static void __"; 3423243791Sdim 3424243791Sdim S += funcName; 3425243791Sdim S += "_block_copy_" + utostr(i); 3426243791Sdim S += "(" + StructRef; 3427243791Sdim S += "*dst, " + StructRef; 3428243791Sdim S += "*src) {"; 3429243791Sdim for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 3430243791Sdim E = ImportedBlockDecls.end(); I != E; ++I) { 3431243791Sdim ValueDecl *VD = (*I); 3432243791Sdim S += "_Block_object_assign((void*)&dst->"; 3433243791Sdim S += (*I)->getNameAsString(); 3434243791Sdim S += ", (void*)src->"; 3435243791Sdim S += (*I)->getNameAsString(); 3436243791Sdim if (BlockByRefDeclsPtrSet.count((*I))) 3437243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 3438243791Sdim else if (VD->getType()->isBlockPointerType()) 3439243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 3440243791Sdim else 3441243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 3442243791Sdim } 3443243791Sdim S += "}\n"; 3444243791Sdim 3445243791Sdim S += "\nstatic void __"; 3446243791Sdim S += funcName; 3447243791Sdim S += "_block_dispose_" + utostr(i); 3448243791Sdim S += "(" + StructRef; 3449243791Sdim S += "*src) {"; 3450243791Sdim for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 3451243791Sdim E = ImportedBlockDecls.end(); I != E; ++I) { 3452243791Sdim ValueDecl *VD = (*I); 3453243791Sdim S += "_Block_object_dispose((void*)src->"; 3454243791Sdim S += (*I)->getNameAsString(); 3455243791Sdim if (BlockByRefDeclsPtrSet.count((*I))) 3456243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 3457243791Sdim else if (VD->getType()->isBlockPointerType()) 3458243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 3459243791Sdim else 3460243791Sdim S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 3461243791Sdim } 3462243791Sdim S += "}\n"; 3463243791Sdim return S; 3464243791Sdim} 3465243791Sdim 3466243791Sdimstd::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 3467243791Sdim std::string Desc) { 3468243791Sdim std::string S = "\nstruct " + Tag; 3469243791Sdim std::string Constructor = " " + Tag; 3470243791Sdim 3471243791Sdim S += " {\n struct __block_impl impl;\n"; 3472243791Sdim S += " struct " + Desc; 3473243791Sdim S += "* Desc;\n"; 3474243791Sdim 3475243791Sdim Constructor += "(void *fp, "; // Invoke function pointer. 3476243791Sdim Constructor += "struct " + Desc; // Descriptor pointer. 3477243791Sdim Constructor += " *desc"; 3478243791Sdim 3479243791Sdim if (BlockDeclRefs.size()) { 3480243791Sdim // Output all "by copy" declarations. 3481263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 3482243791Sdim E = BlockByCopyDecls.end(); I != E; ++I) { 3483243791Sdim S += " "; 3484243791Sdim std::string FieldName = (*I)->getNameAsString(); 3485243791Sdim std::string ArgName = "_" + FieldName; 3486243791Sdim // Handle nested closure invocation. For example: 3487243791Sdim // 3488243791Sdim // void (^myImportedBlock)(void); 3489243791Sdim // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 3490243791Sdim // 3491243791Sdim // void (^anotherBlock)(void); 3492243791Sdim // anotherBlock = ^(void) { 3493243791Sdim // myImportedBlock(); // import and invoke the closure 3494243791Sdim // }; 3495243791Sdim // 3496243791Sdim if (isTopLevelBlockPointerType((*I)->getType())) { 3497243791Sdim S += "struct __block_impl *"; 3498243791Sdim Constructor += ", void *" + ArgName; 3499243791Sdim } else { 3500243791Sdim QualType QT = (*I)->getType(); 3501243791Sdim if (HasLocalVariableExternalStorage(*I)) 3502243791Sdim QT = Context->getPointerType(QT); 3503243791Sdim QT.getAsStringInternal(FieldName, Context->getPrintingPolicy()); 3504243791Sdim QT.getAsStringInternal(ArgName, Context->getPrintingPolicy()); 3505243791Sdim Constructor += ", " + ArgName; 3506243791Sdim } 3507243791Sdim S += FieldName + ";\n"; 3508243791Sdim } 3509243791Sdim // Output all "by ref" declarations. 3510263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 3511243791Sdim E = BlockByRefDecls.end(); I != E; ++I) { 3512243791Sdim S += " "; 3513243791Sdim std::string FieldName = (*I)->getNameAsString(); 3514243791Sdim std::string ArgName = "_" + FieldName; 3515243791Sdim { 3516243791Sdim std::string TypeString; 3517243791Sdim RewriteByRefString(TypeString, FieldName, (*I)); 3518243791Sdim TypeString += " *"; 3519243791Sdim FieldName = TypeString + FieldName; 3520243791Sdim ArgName = TypeString + ArgName; 3521243791Sdim Constructor += ", " + ArgName; 3522243791Sdim } 3523243791Sdim S += FieldName + "; // by ref\n"; 3524243791Sdim } 3525243791Sdim // Finish writing the constructor. 3526243791Sdim Constructor += ", int flags=0)"; 3527243791Sdim // Initialize all "by copy" arguments. 3528243791Sdim bool firsTime = true; 3529263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 3530243791Sdim E = BlockByCopyDecls.end(); I != E; ++I) { 3531243791Sdim std::string Name = (*I)->getNameAsString(); 3532243791Sdim if (firsTime) { 3533243791Sdim Constructor += " : "; 3534243791Sdim firsTime = false; 3535243791Sdim } 3536243791Sdim else 3537243791Sdim Constructor += ", "; 3538243791Sdim if (isTopLevelBlockPointerType((*I)->getType())) 3539243791Sdim Constructor += Name + "((struct __block_impl *)_" + Name + ")"; 3540243791Sdim else 3541243791Sdim Constructor += Name + "(_" + Name + ")"; 3542243791Sdim } 3543243791Sdim // Initialize all "by ref" arguments. 3544263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 3545243791Sdim E = BlockByRefDecls.end(); I != E; ++I) { 3546243791Sdim std::string Name = (*I)->getNameAsString(); 3547243791Sdim if (firsTime) { 3548243791Sdim Constructor += " : "; 3549243791Sdim firsTime = false; 3550243791Sdim } 3551243791Sdim else 3552243791Sdim Constructor += ", "; 3553243791Sdim Constructor += Name + "(_" + Name + "->__forwarding)"; 3554243791Sdim } 3555243791Sdim 3556243791Sdim Constructor += " {\n"; 3557243791Sdim if (GlobalVarDecl) 3558243791Sdim Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 3559243791Sdim else 3560243791Sdim Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 3561243791Sdim Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 3562243791Sdim 3563243791Sdim Constructor += " Desc = desc;\n"; 3564243791Sdim } else { 3565243791Sdim // Finish writing the constructor. 3566243791Sdim Constructor += ", int flags=0) {\n"; 3567243791Sdim if (GlobalVarDecl) 3568243791Sdim Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 3569243791Sdim else 3570243791Sdim Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 3571243791Sdim Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 3572243791Sdim Constructor += " Desc = desc;\n"; 3573243791Sdim } 3574243791Sdim Constructor += " "; 3575243791Sdim Constructor += "}\n"; 3576243791Sdim S += Constructor; 3577243791Sdim S += "};\n"; 3578243791Sdim return S; 3579243791Sdim} 3580243791Sdim 3581243791Sdimstd::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, 3582243791Sdim std::string ImplTag, int i, 3583243791Sdim StringRef FunName, 3584243791Sdim unsigned hasCopy) { 3585243791Sdim std::string S = "\nstatic struct " + DescTag; 3586243791Sdim 3587243791Sdim S += " {\n unsigned long reserved;\n"; 3588243791Sdim S += " unsigned long Block_size;\n"; 3589243791Sdim if (hasCopy) { 3590243791Sdim S += " void (*copy)(struct "; 3591243791Sdim S += ImplTag; S += "*, struct "; 3592243791Sdim S += ImplTag; S += "*);\n"; 3593243791Sdim 3594243791Sdim S += " void (*dispose)(struct "; 3595243791Sdim S += ImplTag; S += "*);\n"; 3596243791Sdim } 3597243791Sdim S += "} "; 3598243791Sdim 3599243791Sdim S += DescTag + "_DATA = { 0, sizeof(struct "; 3600243791Sdim S += ImplTag + ")"; 3601243791Sdim if (hasCopy) { 3602243791Sdim S += ", __" + FunName.str() + "_block_copy_" + utostr(i); 3603243791Sdim S += ", __" + FunName.str() + "_block_dispose_" + utostr(i); 3604243791Sdim } 3605243791Sdim S += "};\n"; 3606243791Sdim return S; 3607243791Sdim} 3608243791Sdim 3609243791Sdimvoid RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, 3610243791Sdim StringRef FunName) { 3611243791Sdim // Insert declaration for the function in which block literal is used. 3612243791Sdim if (CurFunctionDeclToDeclareForBlock && !Blocks.empty()) 3613243791Sdim RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 3614243791Sdim bool RewriteSC = (GlobalVarDecl && 3615243791Sdim !Blocks.empty() && 3616243791Sdim GlobalVarDecl->getStorageClass() == SC_Static && 3617243791Sdim GlobalVarDecl->getType().getCVRQualifiers()); 3618243791Sdim if (RewriteSC) { 3619243791Sdim std::string SC(" void __"); 3620243791Sdim SC += GlobalVarDecl->getNameAsString(); 3621243791Sdim SC += "() {}"; 3622243791Sdim InsertText(FunLocStart, SC); 3623243791Sdim } 3624243791Sdim 3625243791Sdim // Insert closures that were part of the function. 3626243791Sdim for (unsigned i = 0, count=0; i < Blocks.size(); i++) { 3627243791Sdim CollectBlockDeclRefInfo(Blocks[i]); 3628243791Sdim // Need to copy-in the inner copied-in variables not actually used in this 3629243791Sdim // block. 3630243791Sdim for (int j = 0; j < InnerDeclRefsCount[i]; j++) { 3631243791Sdim DeclRefExpr *Exp = InnerDeclRefs[count++]; 3632243791Sdim ValueDecl *VD = Exp->getDecl(); 3633243791Sdim BlockDeclRefs.push_back(Exp); 3634243791Sdim if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { 3635243791Sdim BlockByCopyDeclsPtrSet.insert(VD); 3636243791Sdim BlockByCopyDecls.push_back(VD); 3637243791Sdim } 3638243791Sdim if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { 3639243791Sdim BlockByRefDeclsPtrSet.insert(VD); 3640243791Sdim BlockByRefDecls.push_back(VD); 3641243791Sdim } 3642243791Sdim // imported objects in the inner blocks not used in the outer 3643243791Sdim // blocks must be copied/disposed in the outer block as well. 3644243791Sdim if (VD->hasAttr<BlocksAttr>() || 3645243791Sdim VD->getType()->isObjCObjectPointerType() || 3646243791Sdim VD->getType()->isBlockPointerType()) 3647243791Sdim ImportedBlockDecls.insert(VD); 3648243791Sdim } 3649243791Sdim 3650243791Sdim std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i); 3651243791Sdim std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i); 3652243791Sdim 3653243791Sdim std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); 3654243791Sdim 3655243791Sdim InsertText(FunLocStart, CI); 3656243791Sdim 3657243791Sdim std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); 3658243791Sdim 3659243791Sdim InsertText(FunLocStart, CF); 3660243791Sdim 3661243791Sdim if (ImportedBlockDecls.size()) { 3662243791Sdim std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); 3663243791Sdim InsertText(FunLocStart, HF); 3664243791Sdim } 3665243791Sdim std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, 3666243791Sdim ImportedBlockDecls.size() > 0); 3667243791Sdim InsertText(FunLocStart, BD); 3668243791Sdim 3669243791Sdim BlockDeclRefs.clear(); 3670243791Sdim BlockByRefDecls.clear(); 3671243791Sdim BlockByRefDeclsPtrSet.clear(); 3672243791Sdim BlockByCopyDecls.clear(); 3673243791Sdim BlockByCopyDeclsPtrSet.clear(); 3674243791Sdim ImportedBlockDecls.clear(); 3675243791Sdim } 3676243791Sdim if (RewriteSC) { 3677243791Sdim // Must insert any 'const/volatile/static here. Since it has been 3678243791Sdim // removed as result of rewriting of block literals. 3679243791Sdim std::string SC; 3680243791Sdim if (GlobalVarDecl->getStorageClass() == SC_Static) 3681243791Sdim SC = "static "; 3682243791Sdim if (GlobalVarDecl->getType().isConstQualified()) 3683243791Sdim SC += "const "; 3684243791Sdim if (GlobalVarDecl->getType().isVolatileQualified()) 3685243791Sdim SC += "volatile "; 3686243791Sdim if (GlobalVarDecl->getType().isRestrictQualified()) 3687243791Sdim SC += "restrict "; 3688243791Sdim InsertText(FunLocStart, SC); 3689243791Sdim } 3690243791Sdim 3691243791Sdim Blocks.clear(); 3692243791Sdim InnerDeclRefsCount.clear(); 3693243791Sdim InnerDeclRefs.clear(); 3694243791Sdim RewrittenBlockExprs.clear(); 3695243791Sdim} 3696243791Sdim 3697243791Sdimvoid RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { 3698243791Sdim SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 3699243791Sdim StringRef FuncName = FD->getName(); 3700243791Sdim 3701243791Sdim SynthesizeBlockLiterals(FunLocStart, FuncName); 3702243791Sdim} 3703243791Sdim 3704243791Sdimstatic void BuildUniqueMethodName(std::string &Name, 3705243791Sdim ObjCMethodDecl *MD) { 3706243791Sdim ObjCInterfaceDecl *IFace = MD->getClassInterface(); 3707243791Sdim Name = IFace->getName(); 3708243791Sdim Name += "__" + MD->getSelector().getAsString(); 3709243791Sdim // Convert colons to underscores. 3710243791Sdim std::string::size_type loc = 0; 3711243791Sdim while ((loc = Name.find(":", loc)) != std::string::npos) 3712243791Sdim Name.replace(loc, 1, "_"); 3713243791Sdim} 3714243791Sdim 3715243791Sdimvoid RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { 3716243791Sdim //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); 3717243791Sdim //SourceLocation FunLocStart = MD->getLocStart(); 3718243791Sdim SourceLocation FunLocStart = MD->getLocStart(); 3719243791Sdim std::string FuncName; 3720243791Sdim BuildUniqueMethodName(FuncName, MD); 3721243791Sdim SynthesizeBlockLiterals(FunLocStart, FuncName); 3722243791Sdim} 3723243791Sdim 3724243791Sdimvoid RewriteObjC::GetBlockDeclRefExprs(Stmt *S) { 3725243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 3726243791Sdim if (*CI) { 3727243791Sdim if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) 3728243791Sdim GetBlockDeclRefExprs(CBE->getBody()); 3729243791Sdim else 3730243791Sdim GetBlockDeclRefExprs(*CI); 3731243791Sdim } 3732243791Sdim // Handle specific things. 3733243791Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 3734243791Sdim if (DRE->refersToEnclosingLocal()) { 3735243791Sdim // FIXME: Handle enums. 3736243791Sdim if (!isa<FunctionDecl>(DRE->getDecl())) 3737243791Sdim BlockDeclRefs.push_back(DRE); 3738243791Sdim if (HasLocalVariableExternalStorage(DRE->getDecl())) 3739243791Sdim BlockDeclRefs.push_back(DRE); 3740243791Sdim } 3741243791Sdim } 3742243791Sdim 3743243791Sdim return; 3744243791Sdim} 3745243791Sdim 3746263508Sdimvoid RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, 3747263508Sdim SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs, 3748243791Sdim llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) { 3749243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 3750243791Sdim if (*CI) { 3751243791Sdim if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) { 3752243791Sdim InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl())); 3753243791Sdim GetInnerBlockDeclRefExprs(CBE->getBody(), 3754243791Sdim InnerBlockDeclRefs, 3755243791Sdim InnerContexts); 3756243791Sdim } 3757243791Sdim else 3758243791Sdim GetInnerBlockDeclRefExprs(*CI, 3759243791Sdim InnerBlockDeclRefs, 3760243791Sdim InnerContexts); 3761243791Sdim 3762243791Sdim } 3763243791Sdim // Handle specific things. 3764243791Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 3765243791Sdim if (DRE->refersToEnclosingLocal()) { 3766243791Sdim if (!isa<FunctionDecl>(DRE->getDecl()) && 3767243791Sdim !InnerContexts.count(DRE->getDecl()->getDeclContext())) 3768243791Sdim InnerBlockDeclRefs.push_back(DRE); 3769243791Sdim if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) 3770243791Sdim if (Var->isFunctionOrMethodVarDecl()) 3771243791Sdim ImportedLocalExternalDecls.insert(Var); 3772243791Sdim } 3773243791Sdim } 3774243791Sdim 3775243791Sdim return; 3776243791Sdim} 3777243791Sdim 3778243791Sdim/// convertFunctionTypeOfBlocks - This routine converts a function type 3779243791Sdim/// whose result type may be a block pointer or whose argument type(s) 3780243791Sdim/// might be block pointers to an equivalent function type replacing 3781243791Sdim/// all block pointers to function pointers. 3782243791SdimQualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { 3783243791Sdim const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 3784243791Sdim // FTP will be null for closures that don't take arguments. 3785243791Sdim // Generate a funky cast. 3786243791Sdim SmallVector<QualType, 8> ArgTypes; 3787243791Sdim QualType Res = FT->getResultType(); 3788243791Sdim bool HasBlockType = convertBlockPointerToFunctionPointer(Res); 3789243791Sdim 3790243791Sdim if (FTP) { 3791243791Sdim for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 3792243791Sdim E = FTP->arg_type_end(); I && (I != E); ++I) { 3793243791Sdim QualType t = *I; 3794243791Sdim // Make sure we convert "t (^)(...)" to "t (*)(...)". 3795243791Sdim if (convertBlockPointerToFunctionPointer(t)) 3796243791Sdim HasBlockType = true; 3797243791Sdim ArgTypes.push_back(t); 3798243791Sdim } 3799243791Sdim } 3800243791Sdim QualType FuncType; 3801243791Sdim // FIXME. Does this work if block takes no argument but has a return type 3802243791Sdim // which is of block type? 3803243791Sdim if (HasBlockType) 3804249423Sdim FuncType = getSimpleFunctionType(Res, ArgTypes); 3805243791Sdim else FuncType = QualType(FT, 0); 3806243791Sdim return FuncType; 3807243791Sdim} 3808243791Sdim 3809243791SdimStmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 3810243791Sdim // Navigate to relevant type information. 3811243791Sdim const BlockPointerType *CPT = 0; 3812243791Sdim 3813243791Sdim if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { 3814243791Sdim CPT = DRE->getType()->getAs<BlockPointerType>(); 3815243791Sdim } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { 3816243791Sdim CPT = MExpr->getType()->getAs<BlockPointerType>(); 3817243791Sdim } 3818243791Sdim else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) { 3819243791Sdim return SynthesizeBlockCall(Exp, PRE->getSubExpr()); 3820243791Sdim } 3821243791Sdim else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 3822243791Sdim CPT = IEXPR->getType()->getAs<BlockPointerType>(); 3823243791Sdim else if (const ConditionalOperator *CEXPR = 3824243791Sdim dyn_cast<ConditionalOperator>(BlockExp)) { 3825243791Sdim Expr *LHSExp = CEXPR->getLHS(); 3826243791Sdim Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp); 3827243791Sdim Expr *RHSExp = CEXPR->getRHS(); 3828243791Sdim Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); 3829243791Sdim Expr *CONDExp = CEXPR->getCond(); 3830243791Sdim ConditionalOperator *CondExpr = 3831243791Sdim new (Context) ConditionalOperator(CONDExp, 3832243791Sdim SourceLocation(), cast<Expr>(LHSStmt), 3833243791Sdim SourceLocation(), cast<Expr>(RHSStmt), 3834243791Sdim Exp->getType(), VK_RValue, OK_Ordinary); 3835243791Sdim return CondExpr; 3836243791Sdim } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { 3837243791Sdim CPT = IRE->getType()->getAs<BlockPointerType>(); 3838243791Sdim } else if (const PseudoObjectExpr *POE 3839243791Sdim = dyn_cast<PseudoObjectExpr>(BlockExp)) { 3840243791Sdim CPT = POE->getType()->castAs<BlockPointerType>(); 3841243791Sdim } else { 3842243791Sdim assert(1 && "RewriteBlockClass: Bad type"); 3843243791Sdim } 3844243791Sdim assert(CPT && "RewriteBlockClass: Bad type"); 3845243791Sdim const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); 3846243791Sdim assert(FT && "RewriteBlockClass: Bad type"); 3847243791Sdim const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 3848243791Sdim // FTP will be null for closures that don't take arguments. 3849243791Sdim 3850243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 3851243791Sdim SourceLocation(), SourceLocation(), 3852243791Sdim &Context->Idents.get("__block_impl")); 3853243791Sdim QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); 3854243791Sdim 3855243791Sdim // Generate a funky cast. 3856243791Sdim SmallVector<QualType, 8> ArgTypes; 3857243791Sdim 3858243791Sdim // Push the block argument type. 3859243791Sdim ArgTypes.push_back(PtrBlock); 3860243791Sdim if (FTP) { 3861243791Sdim for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 3862243791Sdim E = FTP->arg_type_end(); I && (I != E); ++I) { 3863243791Sdim QualType t = *I; 3864243791Sdim // Make sure we convert "t (^)(...)" to "t (*)(...)". 3865243791Sdim if (!convertBlockPointerToFunctionPointer(t)) 3866243791Sdim convertToUnqualifiedObjCType(t); 3867243791Sdim ArgTypes.push_back(t); 3868243791Sdim } 3869243791Sdim } 3870243791Sdim // Now do the pointer to function cast. 3871249423Sdim QualType PtrToFuncCastType = getSimpleFunctionType(Exp->getType(), ArgTypes); 3872243791Sdim 3873243791Sdim PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); 3874243791Sdim 3875243791Sdim CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock, 3876243791Sdim CK_BitCast, 3877243791Sdim const_cast<Expr*>(BlockExp)); 3878243791Sdim // Don't forget the parens to enforce the proper binding. 3879243791Sdim ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 3880243791Sdim BlkCast); 3881243791Sdim //PE->dump(); 3882243791Sdim 3883243791Sdim FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 3884243791Sdim SourceLocation(), 3885243791Sdim &Context->Idents.get("FuncPtr"), 3886243791Sdim Context->VoidPtrTy, 0, 3887243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 3888243791Sdim ICIS_NoInit); 3889243791Sdim MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 3890243791Sdim FD->getType(), VK_LValue, 3891243791Sdim OK_Ordinary); 3892243791Sdim 3893243791Sdim 3894243791Sdim CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, 3895243791Sdim CK_BitCast, ME); 3896243791Sdim PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); 3897243791Sdim 3898243791Sdim SmallVector<Expr*, 8> BlkExprs; 3899243791Sdim // Add the implicit argument. 3900243791Sdim BlkExprs.push_back(BlkCast); 3901243791Sdim // Add the user arguments. 3902243791Sdim for (CallExpr::arg_iterator I = Exp->arg_begin(), 3903243791Sdim E = Exp->arg_end(); I != E; ++I) { 3904243791Sdim BlkExprs.push_back(*I); 3905243791Sdim } 3906243791Sdim CallExpr *CE = new (Context) CallExpr(*Context, PE, BlkExprs, 3907243791Sdim Exp->getType(), VK_RValue, 3908243791Sdim SourceLocation()); 3909243791Sdim return CE; 3910243791Sdim} 3911243791Sdim 3912243791Sdim// We need to return the rewritten expression to handle cases where the 3913243791Sdim// BlockDeclRefExpr is embedded in another expression being rewritten. 3914243791Sdim// For example: 3915243791Sdim// 3916243791Sdim// int main() { 3917243791Sdim// __block Foo *f; 3918243791Sdim// __block int i; 3919243791Sdim// 3920243791Sdim// void (^myblock)() = ^() { 3921243791Sdim// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten). 3922243791Sdim// i = 77; 3923243791Sdim// }; 3924243791Sdim//} 3925243791SdimStmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { 3926243791Sdim // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 3927243791Sdim // for each DeclRefExp where BYREFVAR is name of the variable. 3928243791Sdim ValueDecl *VD = DeclRefExp->getDecl(); 3929243791Sdim bool isArrow = DeclRefExp->refersToEnclosingLocal(); 3930243791Sdim 3931243791Sdim FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 3932243791Sdim SourceLocation(), 3933243791Sdim &Context->Idents.get("__forwarding"), 3934243791Sdim Context->VoidPtrTy, 0, 3935243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 3936243791Sdim ICIS_NoInit); 3937243791Sdim MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow, 3938243791Sdim FD, SourceLocation(), 3939243791Sdim FD->getType(), VK_LValue, 3940243791Sdim OK_Ordinary); 3941243791Sdim 3942243791Sdim StringRef Name = VD->getName(); 3943243791Sdim FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 3944243791Sdim &Context->Idents.get(Name), 3945243791Sdim Context->VoidPtrTy, 0, 3946243791Sdim /*BitWidth=*/0, /*Mutable=*/true, 3947243791Sdim ICIS_NoInit); 3948243791Sdim ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(), 3949243791Sdim DeclRefExp->getType(), VK_LValue, OK_Ordinary); 3950243791Sdim 3951243791Sdim 3952243791Sdim 3953243791Sdim // Need parens to enforce precedence. 3954243791Sdim ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 3955243791Sdim DeclRefExp->getExprLoc(), 3956243791Sdim ME); 3957243791Sdim ReplaceStmt(DeclRefExp, PE); 3958243791Sdim return PE; 3959243791Sdim} 3960243791Sdim 3961243791Sdim// Rewrites the imported local variable V with external storage 3962243791Sdim// (static, extern, etc.) as *V 3963243791Sdim// 3964243791SdimStmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { 3965243791Sdim ValueDecl *VD = DRE->getDecl(); 3966243791Sdim if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 3967243791Sdim if (!ImportedLocalExternalDecls.count(Var)) 3968243791Sdim return DRE; 3969243791Sdim Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), 3970243791Sdim VK_LValue, OK_Ordinary, 3971243791Sdim DRE->getLocation()); 3972243791Sdim // Need parens to enforce precedence. 3973243791Sdim ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 3974243791Sdim Exp); 3975243791Sdim ReplaceStmt(DRE, PE); 3976243791Sdim return PE; 3977243791Sdim} 3978243791Sdim 3979243791Sdimvoid RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { 3980243791Sdim SourceLocation LocStart = CE->getLParenLoc(); 3981243791Sdim SourceLocation LocEnd = CE->getRParenLoc(); 3982243791Sdim 3983243791Sdim // Need to avoid trying to rewrite synthesized casts. 3984243791Sdim if (LocStart.isInvalid()) 3985243791Sdim return; 3986243791Sdim // Need to avoid trying to rewrite casts contained in macros. 3987243791Sdim if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) 3988243791Sdim return; 3989243791Sdim 3990243791Sdim const char *startBuf = SM->getCharacterData(LocStart); 3991243791Sdim const char *endBuf = SM->getCharacterData(LocEnd); 3992243791Sdim QualType QT = CE->getType(); 3993243791Sdim const Type* TypePtr = QT->getAs<Type>(); 3994243791Sdim if (isa<TypeOfExprType>(TypePtr)) { 3995243791Sdim const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 3996243791Sdim QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 3997243791Sdim std::string TypeAsString = "("; 3998243791Sdim RewriteBlockPointerType(TypeAsString, QT); 3999243791Sdim TypeAsString += ")"; 4000243791Sdim ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); 4001243791Sdim return; 4002243791Sdim } 4003243791Sdim // advance the location to startArgList. 4004243791Sdim const char *argPtr = startBuf; 4005243791Sdim 4006243791Sdim while (*argPtr++ && (argPtr < endBuf)) { 4007243791Sdim switch (*argPtr) { 4008243791Sdim case '^': 4009243791Sdim // Replace the '^' with '*'. 4010243791Sdim LocStart = LocStart.getLocWithOffset(argPtr-startBuf); 4011243791Sdim ReplaceText(LocStart, 1, "*"); 4012243791Sdim break; 4013243791Sdim } 4014243791Sdim } 4015243791Sdim return; 4016243791Sdim} 4017243791Sdim 4018243791Sdimvoid RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { 4019243791Sdim SourceLocation DeclLoc = FD->getLocation(); 4020243791Sdim unsigned parenCount = 0; 4021243791Sdim 4022243791Sdim // We have 1 or more arguments that have closure pointers. 4023243791Sdim const char *startBuf = SM->getCharacterData(DeclLoc); 4024243791Sdim const char *startArgList = strchr(startBuf, '('); 4025243791Sdim 4026243791Sdim assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); 4027243791Sdim 4028243791Sdim parenCount++; 4029243791Sdim // advance the location to startArgList. 4030243791Sdim DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf); 4031243791Sdim assert((DeclLoc.isValid()) && "Invalid DeclLoc"); 4032243791Sdim 4033243791Sdim const char *argPtr = startArgList; 4034243791Sdim 4035243791Sdim while (*argPtr++ && parenCount) { 4036243791Sdim switch (*argPtr) { 4037243791Sdim case '^': 4038243791Sdim // Replace the '^' with '*'. 4039243791Sdim DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList); 4040243791Sdim ReplaceText(DeclLoc, 1, "*"); 4041243791Sdim break; 4042243791Sdim case '(': 4043243791Sdim parenCount++; 4044243791Sdim break; 4045243791Sdim case ')': 4046243791Sdim parenCount--; 4047243791Sdim break; 4048243791Sdim } 4049243791Sdim } 4050243791Sdim return; 4051243791Sdim} 4052243791Sdim 4053243791Sdimbool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { 4054243791Sdim const FunctionProtoType *FTP; 4055243791Sdim const PointerType *PT = QT->getAs<PointerType>(); 4056243791Sdim if (PT) { 4057243791Sdim FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 4058243791Sdim } else { 4059243791Sdim const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 4060243791Sdim assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 4061243791Sdim FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 4062243791Sdim } 4063243791Sdim if (FTP) { 4064243791Sdim for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 4065243791Sdim E = FTP->arg_type_end(); I != E; ++I) 4066243791Sdim if (isTopLevelBlockPointerType(*I)) 4067243791Sdim return true; 4068243791Sdim } 4069243791Sdim return false; 4070243791Sdim} 4071243791Sdim 4072243791Sdimbool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) { 4073243791Sdim const FunctionProtoType *FTP; 4074243791Sdim const PointerType *PT = QT->getAs<PointerType>(); 4075243791Sdim if (PT) { 4076243791Sdim FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 4077243791Sdim } else { 4078243791Sdim const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 4079243791Sdim assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 4080243791Sdim FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 4081243791Sdim } 4082243791Sdim if (FTP) { 4083243791Sdim for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 4084243791Sdim E = FTP->arg_type_end(); I != E; ++I) { 4085243791Sdim if ((*I)->isObjCQualifiedIdType()) 4086243791Sdim return true; 4087243791Sdim if ((*I)->isObjCObjectPointerType() && 4088243791Sdim (*I)->getPointeeType()->isObjCQualifiedInterfaceType()) 4089243791Sdim return true; 4090243791Sdim } 4091243791Sdim 4092243791Sdim } 4093243791Sdim return false; 4094243791Sdim} 4095243791Sdim 4096243791Sdimvoid RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen, 4097243791Sdim const char *&RParen) { 4098243791Sdim const char *argPtr = strchr(Name, '('); 4099243791Sdim assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); 4100243791Sdim 4101243791Sdim LParen = argPtr; // output the start. 4102243791Sdim argPtr++; // skip past the left paren. 4103243791Sdim unsigned parenCount = 1; 4104243791Sdim 4105243791Sdim while (*argPtr && parenCount) { 4106243791Sdim switch (*argPtr) { 4107243791Sdim case '(': parenCount++; break; 4108243791Sdim case ')': parenCount--; break; 4109243791Sdim default: break; 4110243791Sdim } 4111243791Sdim if (parenCount) argPtr++; 4112243791Sdim } 4113243791Sdim assert((*argPtr == ')') && "Rewriter fuzzy parser confused"); 4114243791Sdim RParen = argPtr; // output the end 4115243791Sdim} 4116243791Sdim 4117243791Sdimvoid RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { 4118243791Sdim if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 4119243791Sdim RewriteBlockPointerFunctionArgs(FD); 4120243791Sdim return; 4121243791Sdim } 4122243791Sdim // Handle Variables and Typedefs. 4123243791Sdim SourceLocation DeclLoc = ND->getLocation(); 4124243791Sdim QualType DeclT; 4125243791Sdim if (VarDecl *VD = dyn_cast<VarDecl>(ND)) 4126243791Sdim DeclT = VD->getType(); 4127243791Sdim else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND)) 4128243791Sdim DeclT = TDD->getUnderlyingType(); 4129243791Sdim else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) 4130243791Sdim DeclT = FD->getType(); 4131243791Sdim else 4132243791Sdim llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled"); 4133243791Sdim 4134243791Sdim const char *startBuf = SM->getCharacterData(DeclLoc); 4135243791Sdim const char *endBuf = startBuf; 4136243791Sdim // scan backward (from the decl location) for the end of the previous decl. 4137243791Sdim while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) 4138243791Sdim startBuf--; 4139243791Sdim SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf); 4140243791Sdim std::string buf; 4141243791Sdim unsigned OrigLength=0; 4142243791Sdim // *startBuf != '^' if we are dealing with a pointer to function that 4143243791Sdim // may take block argument types (which will be handled below). 4144243791Sdim if (*startBuf == '^') { 4145243791Sdim // Replace the '^' with '*', computing a negative offset. 4146243791Sdim buf = '*'; 4147243791Sdim startBuf++; 4148243791Sdim OrigLength++; 4149243791Sdim } 4150243791Sdim while (*startBuf != ')') { 4151243791Sdim buf += *startBuf; 4152243791Sdim startBuf++; 4153243791Sdim OrigLength++; 4154243791Sdim } 4155243791Sdim buf += ')'; 4156243791Sdim OrigLength++; 4157243791Sdim 4158243791Sdim if (PointerTypeTakesAnyBlockArguments(DeclT) || 4159243791Sdim PointerTypeTakesAnyObjCQualifiedType(DeclT)) { 4160243791Sdim // Replace the '^' with '*' for arguments. 4161243791Sdim // Replace id<P> with id/*<>*/ 4162243791Sdim DeclLoc = ND->getLocation(); 4163243791Sdim startBuf = SM->getCharacterData(DeclLoc); 4164243791Sdim const char *argListBegin, *argListEnd; 4165243791Sdim GetExtentOfArgList(startBuf, argListBegin, argListEnd); 4166243791Sdim while (argListBegin < argListEnd) { 4167243791Sdim if (*argListBegin == '^') 4168243791Sdim buf += '*'; 4169243791Sdim else if (*argListBegin == '<') { 4170243791Sdim buf += "/*"; 4171243791Sdim buf += *argListBegin++; 4172243791Sdim OrigLength++; 4173243791Sdim while (*argListBegin != '>') { 4174243791Sdim buf += *argListBegin++; 4175243791Sdim OrigLength++; 4176243791Sdim } 4177243791Sdim buf += *argListBegin; 4178243791Sdim buf += "*/"; 4179243791Sdim } 4180243791Sdim else 4181243791Sdim buf += *argListBegin; 4182243791Sdim argListBegin++; 4183243791Sdim OrigLength++; 4184243791Sdim } 4185243791Sdim buf += ')'; 4186243791Sdim OrigLength++; 4187243791Sdim } 4188243791Sdim ReplaceText(Start, OrigLength, buf); 4189243791Sdim 4190243791Sdim return; 4191243791Sdim} 4192243791Sdim 4193243791Sdim 4194243791Sdim/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: 4195243791Sdim/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, 4196243791Sdim/// struct Block_byref_id_object *src) { 4197243791Sdim/// _Block_object_assign (&_dest->object, _src->object, 4198243791Sdim/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 4199243791Sdim/// [|BLOCK_FIELD_IS_WEAK]) // object 4200243791Sdim/// _Block_object_assign(&_dest->object, _src->object, 4201243791Sdim/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 4202243791Sdim/// [|BLOCK_FIELD_IS_WEAK]) // block 4203243791Sdim/// } 4204243791Sdim/// And: 4205243791Sdim/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { 4206243791Sdim/// _Block_object_dispose(_src->object, 4207243791Sdim/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 4208243791Sdim/// [|BLOCK_FIELD_IS_WEAK]) // object 4209243791Sdim/// _Block_object_dispose(_src->object, 4210243791Sdim/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 4211243791Sdim/// [|BLOCK_FIELD_IS_WEAK]) // block 4212243791Sdim/// } 4213243791Sdim 4214243791Sdimstd::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, 4215243791Sdim int flag) { 4216243791Sdim std::string S; 4217243791Sdim if (CopyDestroyCache.count(flag)) 4218243791Sdim return S; 4219243791Sdim CopyDestroyCache.insert(flag); 4220243791Sdim S = "static void __Block_byref_id_object_copy_"; 4221243791Sdim S += utostr(flag); 4222243791Sdim S += "(void *dst, void *src) {\n"; 4223243791Sdim 4224243791Sdim // offset into the object pointer is computed as: 4225243791Sdim // void * + void* + int + int + void* + void * 4226243791Sdim unsigned IntSize = 4227243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 4228243791Sdim unsigned VoidPtrSize = 4229243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); 4230243791Sdim 4231243791Sdim unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth(); 4232243791Sdim S += " _Block_object_assign((char*)dst + "; 4233243791Sdim S += utostr(offset); 4234243791Sdim S += ", *(void * *) ((char*)src + "; 4235243791Sdim S += utostr(offset); 4236243791Sdim S += "), "; 4237243791Sdim S += utostr(flag); 4238243791Sdim S += ");\n}\n"; 4239243791Sdim 4240243791Sdim S += "static void __Block_byref_id_object_dispose_"; 4241243791Sdim S += utostr(flag); 4242243791Sdim S += "(void *src) {\n"; 4243243791Sdim S += " _Block_object_dispose(*(void * *) ((char*)src + "; 4244243791Sdim S += utostr(offset); 4245243791Sdim S += "), "; 4246243791Sdim S += utostr(flag); 4247243791Sdim S += ");\n}\n"; 4248243791Sdim return S; 4249243791Sdim} 4250243791Sdim 4251243791Sdim/// RewriteByRefVar - For each __block typex ND variable this routine transforms 4252243791Sdim/// the declaration into: 4253243791Sdim/// struct __Block_byref_ND { 4254243791Sdim/// void *__isa; // NULL for everything except __weak pointers 4255243791Sdim/// struct __Block_byref_ND *__forwarding; 4256243791Sdim/// int32_t __flags; 4257243791Sdim/// int32_t __size; 4258243791Sdim/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object 4259243791Sdim/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object 4260243791Sdim/// typex ND; 4261243791Sdim/// }; 4262243791Sdim/// 4263243791Sdim/// It then replaces declaration of ND variable with: 4264243791Sdim/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 4265243791Sdim/// __size=sizeof(struct __Block_byref_ND), 4266243791Sdim/// ND=initializer-if-any}; 4267243791Sdim/// 4268243791Sdim/// 4269243791Sdimvoid RewriteObjC::RewriteByRefVar(VarDecl *ND) { 4270243791Sdim // Insert declaration for the function in which block literal is 4271243791Sdim // used. 4272243791Sdim if (CurFunctionDeclToDeclareForBlock) 4273243791Sdim RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 4274243791Sdim int flag = 0; 4275243791Sdim int isa = 0; 4276243791Sdim SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 4277243791Sdim if (DeclLoc.isInvalid()) 4278243791Sdim // If type location is missing, it is because of missing type (a warning). 4279243791Sdim // Use variable's location which is good for this case. 4280243791Sdim DeclLoc = ND->getLocation(); 4281243791Sdim const char *startBuf = SM->getCharacterData(DeclLoc); 4282243791Sdim SourceLocation X = ND->getLocEnd(); 4283243791Sdim X = SM->getExpansionLoc(X); 4284243791Sdim const char *endBuf = SM->getCharacterData(X); 4285243791Sdim std::string Name(ND->getNameAsString()); 4286243791Sdim std::string ByrefType; 4287243791Sdim RewriteByRefString(ByrefType, Name, ND, true); 4288243791Sdim ByrefType += " {\n"; 4289243791Sdim ByrefType += " void *__isa;\n"; 4290243791Sdim RewriteByRefString(ByrefType, Name, ND); 4291243791Sdim ByrefType += " *__forwarding;\n"; 4292243791Sdim ByrefType += " int __flags;\n"; 4293243791Sdim ByrefType += " int __size;\n"; 4294243791Sdim // Add void *__Block_byref_id_object_copy; 4295243791Sdim // void *__Block_byref_id_object_dispose; if needed. 4296243791Sdim QualType Ty = ND->getType(); 4297249423Sdim bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty, ND); 4298243791Sdim if (HasCopyAndDispose) { 4299243791Sdim ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; 4300243791Sdim ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; 4301243791Sdim } 4302243791Sdim 4303243791Sdim QualType T = Ty; 4304243791Sdim (void)convertBlockPointerToFunctionPointer(T); 4305243791Sdim T.getAsStringInternal(Name, Context->getPrintingPolicy()); 4306243791Sdim 4307243791Sdim ByrefType += " " + Name + ";\n"; 4308243791Sdim ByrefType += "};\n"; 4309243791Sdim // Insert this type in global scope. It is needed by helper function. 4310243791Sdim SourceLocation FunLocStart; 4311243791Sdim if (CurFunctionDef) 4312243791Sdim FunLocStart = CurFunctionDef->getTypeSpecStartLoc(); 4313243791Sdim else { 4314243791Sdim assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); 4315243791Sdim FunLocStart = CurMethodDef->getLocStart(); 4316243791Sdim } 4317243791Sdim InsertText(FunLocStart, ByrefType); 4318243791Sdim if (Ty.isObjCGCWeak()) { 4319243791Sdim flag |= BLOCK_FIELD_IS_WEAK; 4320243791Sdim isa = 1; 4321243791Sdim } 4322243791Sdim 4323243791Sdim if (HasCopyAndDispose) { 4324243791Sdim flag = BLOCK_BYREF_CALLER; 4325243791Sdim QualType Ty = ND->getType(); 4326243791Sdim // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. 4327243791Sdim if (Ty->isBlockPointerType()) 4328243791Sdim flag |= BLOCK_FIELD_IS_BLOCK; 4329243791Sdim else 4330243791Sdim flag |= BLOCK_FIELD_IS_OBJECT; 4331243791Sdim std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); 4332243791Sdim if (!HF.empty()) 4333243791Sdim InsertText(FunLocStart, HF); 4334243791Sdim } 4335243791Sdim 4336243791Sdim // struct __Block_byref_ND ND = 4337243791Sdim // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 4338243791Sdim // initializer-if-any}; 4339243791Sdim bool hasInit = (ND->getInit() != 0); 4340243791Sdim unsigned flags = 0; 4341243791Sdim if (HasCopyAndDispose) 4342243791Sdim flags |= BLOCK_HAS_COPY_DISPOSE; 4343243791Sdim Name = ND->getNameAsString(); 4344243791Sdim ByrefType.clear(); 4345243791Sdim RewriteByRefString(ByrefType, Name, ND); 4346243791Sdim std::string ForwardingCastType("("); 4347243791Sdim ForwardingCastType += ByrefType + " *)"; 4348243791Sdim if (!hasInit) { 4349243791Sdim ByrefType += " " + Name + " = {(void*)"; 4350243791Sdim ByrefType += utostr(isa); 4351243791Sdim ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 4352243791Sdim ByrefType += utostr(flags); 4353243791Sdim ByrefType += ", "; 4354243791Sdim ByrefType += "sizeof("; 4355243791Sdim RewriteByRefString(ByrefType, Name, ND); 4356243791Sdim ByrefType += ")"; 4357243791Sdim if (HasCopyAndDispose) { 4358243791Sdim ByrefType += ", __Block_byref_id_object_copy_"; 4359243791Sdim ByrefType += utostr(flag); 4360243791Sdim ByrefType += ", __Block_byref_id_object_dispose_"; 4361243791Sdim ByrefType += utostr(flag); 4362243791Sdim } 4363243791Sdim ByrefType += "};\n"; 4364243791Sdim unsigned nameSize = Name.size(); 4365243791Sdim // for block or function pointer declaration. Name is aleady 4366243791Sdim // part of the declaration. 4367243791Sdim if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) 4368243791Sdim nameSize = 1; 4369243791Sdim ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType); 4370243791Sdim } 4371243791Sdim else { 4372243791Sdim SourceLocation startLoc; 4373243791Sdim Expr *E = ND->getInit(); 4374243791Sdim if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 4375243791Sdim startLoc = ECE->getLParenLoc(); 4376243791Sdim else 4377243791Sdim startLoc = E->getLocStart(); 4378243791Sdim startLoc = SM->getExpansionLoc(startLoc); 4379243791Sdim endBuf = SM->getCharacterData(startLoc); 4380243791Sdim ByrefType += " " + Name; 4381243791Sdim ByrefType += " = {(void*)"; 4382243791Sdim ByrefType += utostr(isa); 4383243791Sdim ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 4384243791Sdim ByrefType += utostr(flags); 4385243791Sdim ByrefType += ", "; 4386243791Sdim ByrefType += "sizeof("; 4387243791Sdim RewriteByRefString(ByrefType, Name, ND); 4388243791Sdim ByrefType += "), "; 4389243791Sdim if (HasCopyAndDispose) { 4390243791Sdim ByrefType += "__Block_byref_id_object_copy_"; 4391243791Sdim ByrefType += utostr(flag); 4392243791Sdim ByrefType += ", __Block_byref_id_object_dispose_"; 4393243791Sdim ByrefType += utostr(flag); 4394243791Sdim ByrefType += ", "; 4395243791Sdim } 4396243791Sdim ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); 4397243791Sdim 4398243791Sdim // Complete the newly synthesized compound expression by inserting a right 4399243791Sdim // curly brace before the end of the declaration. 4400243791Sdim // FIXME: This approach avoids rewriting the initializer expression. It 4401243791Sdim // also assumes there is only one declarator. For example, the following 4402243791Sdim // isn't currently supported by this routine (in general): 4403243791Sdim // 4404243791Sdim // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37; 4405243791Sdim // 4406243791Sdim const char *startInitializerBuf = SM->getCharacterData(startLoc); 4407243791Sdim const char *semiBuf = strchr(startInitializerBuf, ';'); 4408243791Sdim assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'"); 4409243791Sdim SourceLocation semiLoc = 4410243791Sdim startLoc.getLocWithOffset(semiBuf-startInitializerBuf); 4411243791Sdim 4412243791Sdim InsertText(semiLoc, "}"); 4413243791Sdim } 4414243791Sdim return; 4415243791Sdim} 4416243791Sdim 4417243791Sdimvoid RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { 4418243791Sdim // Add initializers for any closure decl refs. 4419243791Sdim GetBlockDeclRefExprs(Exp->getBody()); 4420243791Sdim if (BlockDeclRefs.size()) { 4421243791Sdim // Unique all "by copy" declarations. 4422243791Sdim for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 4423243791Sdim if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 4424243791Sdim if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 4425243791Sdim BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 4426243791Sdim BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); 4427243791Sdim } 4428243791Sdim } 4429243791Sdim // Unique all "by ref" declarations. 4430243791Sdim for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 4431243791Sdim if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 4432243791Sdim if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 4433243791Sdim BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 4434243791Sdim BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); 4435243791Sdim } 4436243791Sdim } 4437243791Sdim // Find any imported blocks...they will need special attention. 4438243791Sdim for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 4439243791Sdim if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 4440243791Sdim BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 4441243791Sdim BlockDeclRefs[i]->getType()->isBlockPointerType()) 4442243791Sdim ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); 4443243791Sdim } 4444243791Sdim} 4445243791Sdim 4446243791SdimFunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) { 4447243791Sdim IdentifierInfo *ID = &Context->Idents.get(name); 4448243791Sdim QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); 4449243791Sdim return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), 4450243791Sdim SourceLocation(), ID, FType, 0, SC_Extern, 4451249423Sdim false, false); 4452243791Sdim} 4453243791Sdim 4454243791SdimStmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, 4455263508Sdim const SmallVectorImpl<DeclRefExpr *> &InnerBlockDeclRefs) { 4456243791Sdim const BlockDecl *block = Exp->getBlockDecl(); 4457243791Sdim Blocks.push_back(Exp); 4458243791Sdim 4459243791Sdim CollectBlockDeclRefInfo(Exp); 4460243791Sdim 4461243791Sdim // Add inner imported variables now used in current block. 4462243791Sdim int countOfInnerDecls = 0; 4463243791Sdim if (!InnerBlockDeclRefs.empty()) { 4464243791Sdim for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { 4465243791Sdim DeclRefExpr *Exp = InnerBlockDeclRefs[i]; 4466243791Sdim ValueDecl *VD = Exp->getDecl(); 4467243791Sdim if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { 4468243791Sdim // We need to save the copied-in variables in nested 4469243791Sdim // blocks because it is needed at the end for some of the API generations. 4470243791Sdim // See SynthesizeBlockLiterals routine. 4471243791Sdim InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 4472243791Sdim BlockDeclRefs.push_back(Exp); 4473243791Sdim BlockByCopyDeclsPtrSet.insert(VD); 4474243791Sdim BlockByCopyDecls.push_back(VD); 4475243791Sdim } 4476243791Sdim if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { 4477243791Sdim InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 4478243791Sdim BlockDeclRefs.push_back(Exp); 4479243791Sdim BlockByRefDeclsPtrSet.insert(VD); 4480243791Sdim BlockByRefDecls.push_back(VD); 4481243791Sdim } 4482243791Sdim } 4483243791Sdim // Find any imported blocks...they will need special attention. 4484243791Sdim for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) 4485243791Sdim if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 4486243791Sdim InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 4487243791Sdim InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) 4488243791Sdim ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); 4489243791Sdim } 4490243791Sdim InnerDeclRefsCount.push_back(countOfInnerDecls); 4491243791Sdim 4492243791Sdim std::string FuncName; 4493243791Sdim 4494243791Sdim if (CurFunctionDef) 4495243791Sdim FuncName = CurFunctionDef->getNameAsString(); 4496243791Sdim else if (CurMethodDef) 4497243791Sdim BuildUniqueMethodName(FuncName, CurMethodDef); 4498243791Sdim else if (GlobalVarDecl) 4499243791Sdim FuncName = std::string(GlobalVarDecl->getNameAsString()); 4500243791Sdim 4501243791Sdim std::string BlockNumber = utostr(Blocks.size()-1); 4502243791Sdim 4503243791Sdim std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber; 4504243791Sdim std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; 4505243791Sdim 4506243791Sdim // Get a pointer to the function type so we can cast appropriately. 4507243791Sdim QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType()); 4508243791Sdim QualType FType = Context->getPointerType(BFT); 4509243791Sdim 4510243791Sdim FunctionDecl *FD; 4511243791Sdim Expr *NewRep; 4512243791Sdim 4513263508Sdim // Simulate a constructor call... 4514243791Sdim FD = SynthBlockInitFunctionDecl(Tag); 4515243791Sdim DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue, 4516243791Sdim SourceLocation()); 4517243791Sdim 4518243791Sdim SmallVector<Expr*, 4> InitExprs; 4519243791Sdim 4520243791Sdim // Initialize the block function. 4521243791Sdim FD = SynthBlockInitFunctionDecl(Func); 4522243791Sdim DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), 4523243791Sdim VK_LValue, SourceLocation()); 4524243791Sdim CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 4525243791Sdim CK_BitCast, Arg); 4526243791Sdim InitExprs.push_back(castExpr); 4527243791Sdim 4528243791Sdim // Initialize the block descriptor. 4529243791Sdim std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; 4530243791Sdim 4531243791Sdim VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, 4532243791Sdim SourceLocation(), SourceLocation(), 4533243791Sdim &Context->Idents.get(DescData.c_str()), 4534243791Sdim Context->VoidPtrTy, 0, 4535249423Sdim SC_Static); 4536243791Sdim UnaryOperator *DescRefExpr = 4537243791Sdim new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false, 4538243791Sdim Context->VoidPtrTy, 4539243791Sdim VK_LValue, 4540243791Sdim SourceLocation()), 4541243791Sdim UO_AddrOf, 4542243791Sdim Context->getPointerType(Context->VoidPtrTy), 4543243791Sdim VK_RValue, OK_Ordinary, 4544243791Sdim SourceLocation()); 4545243791Sdim InitExprs.push_back(DescRefExpr); 4546243791Sdim 4547243791Sdim // Add initializers for any closure decl refs. 4548243791Sdim if (BlockDeclRefs.size()) { 4549243791Sdim Expr *Exp; 4550243791Sdim // Output all "by copy" declarations. 4551263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByCopyDecls.begin(), 4552243791Sdim E = BlockByCopyDecls.end(); I != E; ++I) { 4553243791Sdim if (isObjCType((*I)->getType())) { 4554243791Sdim // FIXME: Conform to ABI ([[obj retain] autorelease]). 4555243791Sdim FD = SynthBlockInitFunctionDecl((*I)->getName()); 4556243791Sdim Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, 4557243791Sdim SourceLocation()); 4558243791Sdim if (HasLocalVariableExternalStorage(*I)) { 4559243791Sdim QualType QT = (*I)->getType(); 4560243791Sdim QT = Context->getPointerType(QT); 4561243791Sdim Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 4562243791Sdim OK_Ordinary, SourceLocation()); 4563243791Sdim } 4564243791Sdim } else if (isTopLevelBlockPointerType((*I)->getType())) { 4565243791Sdim FD = SynthBlockInitFunctionDecl((*I)->getName()); 4566243791Sdim Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, 4567243791Sdim SourceLocation()); 4568243791Sdim Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 4569243791Sdim CK_BitCast, Arg); 4570243791Sdim } else { 4571243791Sdim FD = SynthBlockInitFunctionDecl((*I)->getName()); 4572243791Sdim Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, 4573243791Sdim SourceLocation()); 4574243791Sdim if (HasLocalVariableExternalStorage(*I)) { 4575243791Sdim QualType QT = (*I)->getType(); 4576243791Sdim QT = Context->getPointerType(QT); 4577243791Sdim Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 4578243791Sdim OK_Ordinary, SourceLocation()); 4579243791Sdim } 4580243791Sdim 4581243791Sdim } 4582243791Sdim InitExprs.push_back(Exp); 4583243791Sdim } 4584243791Sdim // Output all "by ref" declarations. 4585263508Sdim for (SmallVectorImpl<ValueDecl *>::iterator I = BlockByRefDecls.begin(), 4586243791Sdim E = BlockByRefDecls.end(); I != E; ++I) { 4587243791Sdim ValueDecl *ND = (*I); 4588243791Sdim std::string Name(ND->getNameAsString()); 4589243791Sdim std::string RecName; 4590243791Sdim RewriteByRefString(RecName, Name, ND, true); 4591243791Sdim IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 4592243791Sdim + sizeof("struct")); 4593243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 4594243791Sdim SourceLocation(), SourceLocation(), 4595243791Sdim II); 4596243791Sdim assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); 4597243791Sdim QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 4598243791Sdim 4599243791Sdim FD = SynthBlockInitFunctionDecl((*I)->getName()); 4600243791Sdim Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, 4601243791Sdim SourceLocation()); 4602243791Sdim bool isNestedCapturedVar = false; 4603243791Sdim if (block) 4604243791Sdim for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 4605243791Sdim ce = block->capture_end(); ci != ce; ++ci) { 4606243791Sdim const VarDecl *variable = ci->getVariable(); 4607243791Sdim if (variable == ND && ci->isNested()) { 4608243791Sdim assert (ci->isByRef() && 4609243791Sdim "SynthBlockInitExpr - captured block variable is not byref"); 4610243791Sdim isNestedCapturedVar = true; 4611243791Sdim break; 4612243791Sdim } 4613243791Sdim } 4614243791Sdim // captured nested byref variable has its address passed. Do not take 4615243791Sdim // its address again. 4616243791Sdim if (!isNestedCapturedVar) 4617243791Sdim Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, 4618243791Sdim Context->getPointerType(Exp->getType()), 4619243791Sdim VK_RValue, OK_Ordinary, SourceLocation()); 4620243791Sdim Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); 4621243791Sdim InitExprs.push_back(Exp); 4622243791Sdim } 4623243791Sdim } 4624243791Sdim if (ImportedBlockDecls.size()) { 4625243791Sdim // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR 4626243791Sdim int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR); 4627243791Sdim unsigned IntSize = 4628243791Sdim static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 4629243791Sdim Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 4630243791Sdim Context->IntTy, SourceLocation()); 4631243791Sdim InitExprs.push_back(FlagExp); 4632243791Sdim } 4633243791Sdim NewRep = new (Context) CallExpr(*Context, DRE, InitExprs, 4634243791Sdim FType, VK_LValue, SourceLocation()); 4635243791Sdim NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, 4636243791Sdim Context->getPointerType(NewRep->getType()), 4637243791Sdim VK_RValue, OK_Ordinary, SourceLocation()); 4638243791Sdim NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, 4639243791Sdim NewRep); 4640243791Sdim BlockDeclRefs.clear(); 4641243791Sdim BlockByRefDecls.clear(); 4642243791Sdim BlockByRefDeclsPtrSet.clear(); 4643243791Sdim BlockByCopyDecls.clear(); 4644243791Sdim BlockByCopyDeclsPtrSet.clear(); 4645243791Sdim ImportedBlockDecls.clear(); 4646243791Sdim return NewRep; 4647243791Sdim} 4648243791Sdim 4649243791Sdimbool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { 4650243791Sdim if (const ObjCForCollectionStmt * CS = 4651243791Sdim dyn_cast<ObjCForCollectionStmt>(Stmts.back())) 4652243791Sdim return CS->getElement() == DS; 4653243791Sdim return false; 4654243791Sdim} 4655243791Sdim 4656243791Sdim//===----------------------------------------------------------------------===// 4657243791Sdim// Function Body / Expression rewriting 4658243791Sdim//===----------------------------------------------------------------------===// 4659243791Sdim 4660243791SdimStmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { 4661243791Sdim if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 4662243791Sdim isa<DoStmt>(S) || isa<ForStmt>(S)) 4663243791Sdim Stmts.push_back(S); 4664243791Sdim else if (isa<ObjCForCollectionStmt>(S)) { 4665243791Sdim Stmts.push_back(S); 4666243791Sdim ObjCBcLabelNo.push_back(++BcLabelCount); 4667243791Sdim } 4668243791Sdim 4669243791Sdim // Pseudo-object operations and ivar references need special 4670243791Sdim // treatment because we're going to recursively rewrite them. 4671243791Sdim if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) { 4672243791Sdim if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) { 4673243791Sdim return RewritePropertyOrImplicitSetter(PseudoOp); 4674243791Sdim } else { 4675243791Sdim return RewritePropertyOrImplicitGetter(PseudoOp); 4676243791Sdim } 4677243791Sdim } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 4678243791Sdim return RewriteObjCIvarRefExpr(IvarRefExpr); 4679243791Sdim } 4680243791Sdim 4681243791Sdim SourceRange OrigStmtRange = S->getSourceRange(); 4682243791Sdim 4683243791Sdim // Perform a bottom up rewrite of all children. 4684243791Sdim for (Stmt::child_range CI = S->children(); CI; ++CI) 4685243791Sdim if (*CI) { 4686243791Sdim Stmt *childStmt = (*CI); 4687243791Sdim Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt); 4688243791Sdim if (newStmt) { 4689243791Sdim *CI = newStmt; 4690243791Sdim } 4691243791Sdim } 4692243791Sdim 4693243791Sdim if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { 4694243791Sdim SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs; 4695243791Sdim llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; 4696243791Sdim InnerContexts.insert(BE->getBlockDecl()); 4697243791Sdim ImportedLocalExternalDecls.clear(); 4698243791Sdim GetInnerBlockDeclRefExprs(BE->getBody(), 4699243791Sdim InnerBlockDeclRefs, InnerContexts); 4700243791Sdim // Rewrite the block body in place. 4701243791Sdim Stmt *SaveCurrentBody = CurrentBody; 4702243791Sdim CurrentBody = BE->getBody(); 4703243791Sdim PropParentMap = 0; 4704243791Sdim // block literal on rhs of a property-dot-sytax assignment 4705243791Sdim // must be replaced by its synthesize ast so getRewrittenText 4706243791Sdim // works as expected. In this case, what actually ends up on RHS 4707243791Sdim // is the blockTranscribed which is the helper function for the 4708243791Sdim // block literal; as in: self.c = ^() {[ace ARR];}; 4709243791Sdim bool saveDisableReplaceStmt = DisableReplaceStmt; 4710243791Sdim DisableReplaceStmt = false; 4711243791Sdim RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); 4712243791Sdim DisableReplaceStmt = saveDisableReplaceStmt; 4713243791Sdim CurrentBody = SaveCurrentBody; 4714243791Sdim PropParentMap = 0; 4715243791Sdim ImportedLocalExternalDecls.clear(); 4716243791Sdim // Now we snarf the rewritten text and stash it away for later use. 4717243791Sdim std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); 4718243791Sdim RewrittenBlockExprs[BE] = Str; 4719243791Sdim 4720243791Sdim Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); 4721243791Sdim 4722243791Sdim //blockTranscribed->dump(); 4723243791Sdim ReplaceStmt(S, blockTranscribed); 4724243791Sdim return blockTranscribed; 4725243791Sdim } 4726243791Sdim // Handle specific things. 4727243791Sdim if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) 4728243791Sdim return RewriteAtEncode(AtEncode); 4729243791Sdim 4730243791Sdim if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) 4731243791Sdim return RewriteAtSelector(AtSelector); 4732243791Sdim 4733243791Sdim if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) 4734243791Sdim return RewriteObjCStringLiteral(AtString); 4735243791Sdim 4736243791Sdim if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { 4737243791Sdim#if 0 4738243791Sdim // Before we rewrite it, put the original message expression in a comment. 4739243791Sdim SourceLocation startLoc = MessExpr->getLocStart(); 4740243791Sdim SourceLocation endLoc = MessExpr->getLocEnd(); 4741243791Sdim 4742243791Sdim const char *startBuf = SM->getCharacterData(startLoc); 4743243791Sdim const char *endBuf = SM->getCharacterData(endLoc); 4744243791Sdim 4745243791Sdim std::string messString; 4746243791Sdim messString += "// "; 4747243791Sdim messString.append(startBuf, endBuf-startBuf+1); 4748243791Sdim messString += "\n"; 4749243791Sdim 4750243791Sdim // FIXME: Missing definition of 4751243791Sdim // InsertText(clang::SourceLocation, char const*, unsigned int). 4752243791Sdim // InsertText(startLoc, messString.c_str(), messString.size()); 4753243791Sdim // Tried this, but it didn't work either... 4754243791Sdim // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); 4755243791Sdim#endif 4756243791Sdim return RewriteMessageExpr(MessExpr); 4757243791Sdim } 4758243791Sdim 4759243791Sdim if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) 4760243791Sdim return RewriteObjCTryStmt(StmtTry); 4761243791Sdim 4762243791Sdim if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) 4763243791Sdim return RewriteObjCSynchronizedStmt(StmtTry); 4764243791Sdim 4765243791Sdim if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) 4766243791Sdim return RewriteObjCThrowStmt(StmtThrow); 4767243791Sdim 4768243791Sdim if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) 4769243791Sdim return RewriteObjCProtocolExpr(ProtocolExp); 4770243791Sdim 4771243791Sdim if (ObjCForCollectionStmt *StmtForCollection = 4772243791Sdim dyn_cast<ObjCForCollectionStmt>(S)) 4773243791Sdim return RewriteObjCForCollectionStmt(StmtForCollection, 4774243791Sdim OrigStmtRange.getEnd()); 4775243791Sdim if (BreakStmt *StmtBreakStmt = 4776243791Sdim dyn_cast<BreakStmt>(S)) 4777243791Sdim return RewriteBreakStmt(StmtBreakStmt); 4778243791Sdim if (ContinueStmt *StmtContinueStmt = 4779243791Sdim dyn_cast<ContinueStmt>(S)) 4780243791Sdim return RewriteContinueStmt(StmtContinueStmt); 4781243791Sdim 4782243791Sdim // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls 4783243791Sdim // and cast exprs. 4784243791Sdim if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 4785243791Sdim // FIXME: What we're doing here is modifying the type-specifier that 4786243791Sdim // precedes the first Decl. In the future the DeclGroup should have 4787243791Sdim // a separate type-specifier that we can rewrite. 4788243791Sdim // NOTE: We need to avoid rewriting the DeclStmt if it is within 4789243791Sdim // the context of an ObjCForCollectionStmt. For example: 4790243791Sdim // NSArray *someArray; 4791243791Sdim // for (id <FooProtocol> index in someArray) ; 4792243791Sdim // This is because RewriteObjCForCollectionStmt() does textual rewriting 4793243791Sdim // and it depends on the original text locations/positions. 4794243791Sdim if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS)) 4795243791Sdim RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); 4796243791Sdim 4797243791Sdim // Blocks rewrite rules. 4798243791Sdim for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 4799243791Sdim DI != DE; ++DI) { 4800243791Sdim Decl *SD = *DI; 4801243791Sdim if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { 4802243791Sdim if (isTopLevelBlockPointerType(ND->getType())) 4803243791Sdim RewriteBlockPointerDecl(ND); 4804243791Sdim else if (ND->getType()->isFunctionPointerType()) 4805243791Sdim CheckFunctionPointerDecl(ND->getType(), ND); 4806243791Sdim if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { 4807243791Sdim if (VD->hasAttr<BlocksAttr>()) { 4808243791Sdim static unsigned uniqueByrefDeclCount = 0; 4809243791Sdim assert(!BlockByRefDeclNo.count(ND) && 4810243791Sdim "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); 4811243791Sdim BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; 4812243791Sdim RewriteByRefVar(VD); 4813243791Sdim } 4814243791Sdim else 4815243791Sdim RewriteTypeOfDecl(VD); 4816243791Sdim } 4817243791Sdim } 4818243791Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { 4819243791Sdim if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 4820243791Sdim RewriteBlockPointerDecl(TD); 4821243791Sdim else if (TD->getUnderlyingType()->isFunctionPointerType()) 4822243791Sdim CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 4823243791Sdim } 4824243791Sdim } 4825243791Sdim } 4826243791Sdim 4827243791Sdim if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) 4828243791Sdim RewriteObjCQualifiedInterfaceTypes(CE); 4829243791Sdim 4830243791Sdim if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 4831243791Sdim isa<DoStmt>(S) || isa<ForStmt>(S)) { 4832243791Sdim assert(!Stmts.empty() && "Statement stack is empty"); 4833243791Sdim assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 4834243791Sdim isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 4835243791Sdim && "Statement stack mismatch"); 4836243791Sdim Stmts.pop_back(); 4837243791Sdim } 4838243791Sdim // Handle blocks rewriting. 4839243791Sdim if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 4840243791Sdim ValueDecl *VD = DRE->getDecl(); 4841243791Sdim if (VD->hasAttr<BlocksAttr>()) 4842243791Sdim return RewriteBlockDeclRefExpr(DRE); 4843243791Sdim if (HasLocalVariableExternalStorage(VD)) 4844243791Sdim return RewriteLocalVariableExternalStorage(DRE); 4845243791Sdim } 4846243791Sdim 4847243791Sdim if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 4848243791Sdim if (CE->getCallee()->getType()->isBlockPointerType()) { 4849243791Sdim Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); 4850243791Sdim ReplaceStmt(S, BlockCall); 4851243791Sdim return BlockCall; 4852243791Sdim } 4853243791Sdim } 4854243791Sdim if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) { 4855243791Sdim RewriteCastExpr(CE); 4856243791Sdim } 4857243791Sdim#if 0 4858243791Sdim if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 4859243791Sdim CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), 4860243791Sdim ICE->getSubExpr(), 4861243791Sdim SourceLocation()); 4862243791Sdim // Get the new text. 4863243791Sdim std::string SStr; 4864243791Sdim llvm::raw_string_ostream Buf(SStr); 4865243791Sdim Replacement->printPretty(Buf); 4866243791Sdim const std::string &Str = Buf.str(); 4867243791Sdim 4868243791Sdim printf("CAST = %s\n", &Str[0]); 4869243791Sdim InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size()); 4870243791Sdim delete S; 4871243791Sdim return Replacement; 4872243791Sdim } 4873243791Sdim#endif 4874243791Sdim // Return this stmt unmodified. 4875243791Sdim return S; 4876243791Sdim} 4877243791Sdim 4878243791Sdimvoid RewriteObjC::RewriteRecordBody(RecordDecl *RD) { 4879243791Sdim for (RecordDecl::field_iterator i = RD->field_begin(), 4880243791Sdim e = RD->field_end(); i != e; ++i) { 4881243791Sdim FieldDecl *FD = *i; 4882243791Sdim if (isTopLevelBlockPointerType(FD->getType())) 4883243791Sdim RewriteBlockPointerDecl(FD); 4884243791Sdim if (FD->getType()->isObjCQualifiedIdType() || 4885243791Sdim FD->getType()->isObjCQualifiedInterfaceType()) 4886243791Sdim RewriteObjCQualifiedInterfaceTypes(FD); 4887243791Sdim } 4888243791Sdim} 4889243791Sdim 4890243791Sdim/// HandleDeclInMainFile - This is called for each top-level decl defined in the 4891243791Sdim/// main file of the input. 4892243791Sdimvoid RewriteObjC::HandleDeclInMainFile(Decl *D) { 4893243791Sdim switch (D->getKind()) { 4894243791Sdim case Decl::Function: { 4895243791Sdim FunctionDecl *FD = cast<FunctionDecl>(D); 4896243791Sdim if (FD->isOverloadedOperator()) 4897243791Sdim return; 4898243791Sdim 4899243791Sdim // Since function prototypes don't have ParmDecl's, we check the function 4900243791Sdim // prototype. This enables us to rewrite function declarations and 4901243791Sdim // definitions using the same code. 4902243791Sdim RewriteBlocksInFunctionProtoType(FD->getType(), FD); 4903243791Sdim 4904243791Sdim if (!FD->isThisDeclarationADefinition()) 4905243791Sdim break; 4906243791Sdim 4907243791Sdim // FIXME: If this should support Obj-C++, support CXXTryStmt 4908243791Sdim if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { 4909243791Sdim CurFunctionDef = FD; 4910243791Sdim CurFunctionDeclToDeclareForBlock = FD; 4911243791Sdim CurrentBody = Body; 4912243791Sdim Body = 4913243791Sdim cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 4914243791Sdim FD->setBody(Body); 4915243791Sdim CurrentBody = 0; 4916243791Sdim if (PropParentMap) { 4917243791Sdim delete PropParentMap; 4918243791Sdim PropParentMap = 0; 4919243791Sdim } 4920243791Sdim // This synthesizes and inserts the block "impl" struct, invoke function, 4921243791Sdim // and any copy/dispose helper functions. 4922243791Sdim InsertBlockLiteralsWithinFunction(FD); 4923243791Sdim CurFunctionDef = 0; 4924243791Sdim CurFunctionDeclToDeclareForBlock = 0; 4925243791Sdim } 4926243791Sdim break; 4927243791Sdim } 4928243791Sdim case Decl::ObjCMethod: { 4929243791Sdim ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); 4930243791Sdim if (CompoundStmt *Body = MD->getCompoundBody()) { 4931243791Sdim CurMethodDef = MD; 4932243791Sdim CurrentBody = Body; 4933243791Sdim Body = 4934243791Sdim cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 4935243791Sdim MD->setBody(Body); 4936243791Sdim CurrentBody = 0; 4937243791Sdim if (PropParentMap) { 4938243791Sdim delete PropParentMap; 4939243791Sdim PropParentMap = 0; 4940243791Sdim } 4941243791Sdim InsertBlockLiteralsWithinMethod(MD); 4942243791Sdim CurMethodDef = 0; 4943243791Sdim } 4944243791Sdim break; 4945243791Sdim } 4946243791Sdim case Decl::ObjCImplementation: { 4947243791Sdim ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D); 4948243791Sdim ClassImplementation.push_back(CI); 4949243791Sdim break; 4950243791Sdim } 4951243791Sdim case Decl::ObjCCategoryImpl: { 4952243791Sdim ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D); 4953243791Sdim CategoryImplementation.push_back(CI); 4954243791Sdim break; 4955243791Sdim } 4956243791Sdim case Decl::Var: { 4957243791Sdim VarDecl *VD = cast<VarDecl>(D); 4958243791Sdim RewriteObjCQualifiedInterfaceTypes(VD); 4959243791Sdim if (isTopLevelBlockPointerType(VD->getType())) 4960243791Sdim RewriteBlockPointerDecl(VD); 4961243791Sdim else if (VD->getType()->isFunctionPointerType()) { 4962243791Sdim CheckFunctionPointerDecl(VD->getType(), VD); 4963243791Sdim if (VD->getInit()) { 4964243791Sdim if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 4965243791Sdim RewriteCastExpr(CE); 4966243791Sdim } 4967243791Sdim } 4968243791Sdim } else if (VD->getType()->isRecordType()) { 4969243791Sdim RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl(); 4970243791Sdim if (RD->isCompleteDefinition()) 4971243791Sdim RewriteRecordBody(RD); 4972243791Sdim } 4973243791Sdim if (VD->getInit()) { 4974243791Sdim GlobalVarDecl = VD; 4975243791Sdim CurrentBody = VD->getInit(); 4976243791Sdim RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); 4977243791Sdim CurrentBody = 0; 4978243791Sdim if (PropParentMap) { 4979243791Sdim delete PropParentMap; 4980243791Sdim PropParentMap = 0; 4981243791Sdim } 4982243791Sdim SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName()); 4983243791Sdim GlobalVarDecl = 0; 4984243791Sdim 4985243791Sdim // This is needed for blocks. 4986243791Sdim if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 4987243791Sdim RewriteCastExpr(CE); 4988243791Sdim } 4989243791Sdim } 4990243791Sdim break; 4991243791Sdim } 4992243791Sdim case Decl::TypeAlias: 4993243791Sdim case Decl::Typedef: { 4994243791Sdim if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 4995243791Sdim if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 4996243791Sdim RewriteBlockPointerDecl(TD); 4997243791Sdim else if (TD->getUnderlyingType()->isFunctionPointerType()) 4998243791Sdim CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 4999243791Sdim } 5000243791Sdim break; 5001243791Sdim } 5002243791Sdim case Decl::CXXRecord: 5003243791Sdim case Decl::Record: { 5004243791Sdim RecordDecl *RD = cast<RecordDecl>(D); 5005243791Sdim if (RD->isCompleteDefinition()) 5006243791Sdim RewriteRecordBody(RD); 5007243791Sdim break; 5008243791Sdim } 5009243791Sdim default: 5010243791Sdim break; 5011243791Sdim } 5012243791Sdim // Nothing yet. 5013243791Sdim} 5014243791Sdim 5015243791Sdimvoid RewriteObjC::HandleTranslationUnit(ASTContext &C) { 5016243791Sdim if (Diags.hasErrorOccurred()) 5017243791Sdim return; 5018243791Sdim 5019243791Sdim RewriteInclude(); 5020243791Sdim 5021243791Sdim // Here's a great place to add any extra declarations that may be needed. 5022243791Sdim // Write out meta data for each @protocol(<expr>). 5023243791Sdim for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 5024243791Sdim E = ProtocolExprDecls.end(); I != E; ++I) 5025243791Sdim RewriteObjCProtocolMetaData(*I, "", "", Preamble); 5026243791Sdim 5027243791Sdim InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); 5028243791Sdim if (ClassImplementation.size() || CategoryImplementation.size()) 5029243791Sdim RewriteImplementations(); 5030243791Sdim 5031243791Sdim // Get the buffer corresponding to MainFileID. If we haven't changed it, then 5032243791Sdim // we are done. 5033243791Sdim if (const RewriteBuffer *RewriteBuf = 5034243791Sdim Rewrite.getRewriteBufferFor(MainFileID)) { 5035243791Sdim //printf("Changed:\n"); 5036243791Sdim *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 5037243791Sdim } else { 5038243791Sdim llvm::errs() << "No changes\n"; 5039243791Sdim } 5040243791Sdim 5041243791Sdim if (ClassImplementation.size() || CategoryImplementation.size() || 5042243791Sdim ProtocolExprDecls.size()) { 5043243791Sdim // Rewrite Objective-c meta data* 5044243791Sdim std::string ResultStr; 5045243791Sdim RewriteMetaDataIntoBuffer(ResultStr); 5046243791Sdim // Emit metadata. 5047243791Sdim *OutFile << ResultStr; 5048243791Sdim } 5049243791Sdim OutFile->flush(); 5050243791Sdim} 5051243791Sdim 5052243791Sdimvoid RewriteObjCFragileABI::Initialize(ASTContext &context) { 5053243791Sdim InitializeCommon(context); 5054243791Sdim 5055243791Sdim // declaring objc_selector outside the parameter list removes a silly 5056243791Sdim // scope related warning... 5057243791Sdim if (IsHeader) 5058243791Sdim Preamble = "#pragma once\n"; 5059243791Sdim Preamble += "struct objc_selector; struct objc_class;\n"; 5060243791Sdim Preamble += "struct __rw_objc_super { struct objc_object *object; "; 5061243791Sdim Preamble += "struct objc_object *superClass; "; 5062243791Sdim if (LangOpts.MicrosoftExt) { 5063243791Sdim // Add a constructor for creating temporary objects. 5064243791Sdim Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) " 5065243791Sdim ": "; 5066243791Sdim Preamble += "object(o), superClass(s) {} "; 5067243791Sdim } 5068243791Sdim Preamble += "};\n"; 5069243791Sdim Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; 5070243791Sdim Preamble += "typedef struct objc_object Protocol;\n"; 5071243791Sdim Preamble += "#define _REWRITER_typedef_Protocol\n"; 5072243791Sdim Preamble += "#endif\n"; 5073243791Sdim if (LangOpts.MicrosoftExt) { 5074243791Sdim Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; 5075243791Sdim Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; 5076243791Sdim } else 5077243791Sdim Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; 5078243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend"; 5079243791Sdim Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5080243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper"; 5081243791Sdim Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 5082243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret"; 5083243791Sdim Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5084243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret"; 5085243791Sdim Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 5086243791Sdim Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret"; 5087243791Sdim Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5088243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass"; 5089243791Sdim Preamble += "(const char *);\n"; 5090243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; 5091243791Sdim Preamble += "(struct objc_class *);\n"; 5092243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass"; 5093243791Sdim Preamble += "(const char *);\n"; 5094243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n"; 5095243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n"; 5096243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n"; 5097243791Sdim Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n"; 5098243791Sdim Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match"; 5099243791Sdim Preamble += "(struct objc_class *, struct objc_object *);\n"; 5100243791Sdim // @synchronized hooks. 5101243791Sdim Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_enter(struct objc_object *);\n"; 5102243791Sdim Preamble += "__OBJC_RW_DLLIMPORT int objc_sync_exit(struct objc_object *);\n"; 5103243791Sdim Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; 5104243791Sdim Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; 5105243791Sdim Preamble += "struct __objcFastEnumerationState {\n\t"; 5106243791Sdim Preamble += "unsigned long state;\n\t"; 5107243791Sdim Preamble += "void **itemsPtr;\n\t"; 5108243791Sdim Preamble += "unsigned long *mutationsPtr;\n\t"; 5109243791Sdim Preamble += "unsigned long extra[5];\n};\n"; 5110243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; 5111243791Sdim Preamble += "#define __FASTENUMERATIONSTATE\n"; 5112243791Sdim Preamble += "#endif\n"; 5113243791Sdim Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; 5114243791Sdim Preamble += "struct __NSConstantStringImpl {\n"; 5115243791Sdim Preamble += " int *isa;\n"; 5116243791Sdim Preamble += " int flags;\n"; 5117243791Sdim Preamble += " char *str;\n"; 5118243791Sdim Preamble += " long length;\n"; 5119243791Sdim Preamble += "};\n"; 5120243791Sdim Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; 5121243791Sdim Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; 5122243791Sdim Preamble += "#else\n"; 5123243791Sdim Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; 5124243791Sdim Preamble += "#endif\n"; 5125243791Sdim Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; 5126243791Sdim Preamble += "#endif\n"; 5127243791Sdim // Blocks preamble. 5128243791Sdim Preamble += "#ifndef BLOCK_IMPL\n"; 5129243791Sdim Preamble += "#define BLOCK_IMPL\n"; 5130243791Sdim Preamble += "struct __block_impl {\n"; 5131243791Sdim Preamble += " void *isa;\n"; 5132243791Sdim Preamble += " int Flags;\n"; 5133243791Sdim Preamble += " int Reserved;\n"; 5134243791Sdim Preamble += " void *FuncPtr;\n"; 5135243791Sdim Preamble += "};\n"; 5136243791Sdim Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; 5137243791Sdim Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; 5138243791Sdim Preamble += "extern \"C\" __declspec(dllexport) " 5139243791Sdim "void _Block_object_assign(void *, const void *, const int);\n"; 5140243791Sdim Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; 5141243791Sdim Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; 5142243791Sdim Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; 5143243791Sdim Preamble += "#else\n"; 5144243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; 5145243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; 5146243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; 5147243791Sdim Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; 5148243791Sdim Preamble += "#endif\n"; 5149243791Sdim Preamble += "#endif\n"; 5150243791Sdim if (LangOpts.MicrosoftExt) { 5151243791Sdim Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; 5152243791Sdim Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; 5153243791Sdim Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. 5154243791Sdim Preamble += "#define __attribute__(X)\n"; 5155243791Sdim Preamble += "#endif\n"; 5156243791Sdim Preamble += "#define __weak\n"; 5157243791Sdim } 5158243791Sdim else { 5159243791Sdim Preamble += "#define __block\n"; 5160243791Sdim Preamble += "#define __weak\n"; 5161243791Sdim } 5162243791Sdim // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long 5163243791Sdim // as this avoids warning in any 64bit/32bit compilation model. 5164243791Sdim Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; 5165243791Sdim} 5166243791Sdim 5167243791Sdim/// RewriteIvarOffsetComputation - This rutine synthesizes computation of 5168243791Sdim/// ivar offset. 5169243791Sdimvoid RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 5170243791Sdim std::string &Result) { 5171243791Sdim if (ivar->isBitField()) { 5172243791Sdim // FIXME: The hack below doesn't work for bitfields. For now, we simply 5173243791Sdim // place all bitfields at offset 0. 5174243791Sdim Result += "0"; 5175243791Sdim } else { 5176243791Sdim Result += "__OFFSETOFIVAR__(struct "; 5177243791Sdim Result += ivar->getContainingInterface()->getNameAsString(); 5178243791Sdim if (LangOpts.MicrosoftExt) 5179243791Sdim Result += "_IMPL"; 5180243791Sdim Result += ", "; 5181243791Sdim Result += ivar->getNameAsString(); 5182243791Sdim Result += ")"; 5183243791Sdim } 5184243791Sdim} 5185243791Sdim 5186243791Sdim/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. 5187243791Sdimvoid RewriteObjCFragileABI::RewriteObjCProtocolMetaData( 5188243791Sdim ObjCProtocolDecl *PDecl, StringRef prefix, 5189243791Sdim StringRef ClassName, std::string &Result) { 5190243791Sdim static bool objc_protocol_methods = false; 5191243791Sdim 5192243791Sdim // Output struct protocol_methods holder of method selector and type. 5193243791Sdim if (!objc_protocol_methods && PDecl->hasDefinition()) { 5194243791Sdim /* struct protocol_methods { 5195243791Sdim SEL _cmd; 5196243791Sdim char *method_types; 5197243791Sdim } 5198243791Sdim */ 5199243791Sdim Result += "\nstruct _protocol_methods {\n"; 5200243791Sdim Result += "\tstruct objc_selector *_cmd;\n"; 5201243791Sdim Result += "\tchar *method_types;\n"; 5202243791Sdim Result += "};\n"; 5203243791Sdim 5204243791Sdim objc_protocol_methods = true; 5205243791Sdim } 5206243791Sdim // Do not synthesize the protocol more than once. 5207243791Sdim if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl())) 5208243791Sdim return; 5209243791Sdim 5210243791Sdim if (ObjCProtocolDecl *Def = PDecl->getDefinition()) 5211243791Sdim PDecl = Def; 5212243791Sdim 5213243791Sdim if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 5214243791Sdim unsigned NumMethods = std::distance(PDecl->instmeth_begin(), 5215243791Sdim PDecl->instmeth_end()); 5216243791Sdim /* struct _objc_protocol_method_list { 5217243791Sdim int protocol_method_count; 5218243791Sdim struct protocol_methods protocols[]; 5219243791Sdim } 5220243791Sdim */ 5221243791Sdim Result += "\nstatic struct {\n"; 5222243791Sdim Result += "\tint protocol_method_count;\n"; 5223243791Sdim Result += "\tstruct _protocol_methods protocol_methods["; 5224243791Sdim Result += utostr(NumMethods); 5225243791Sdim Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_"; 5226243791Sdim Result += PDecl->getNameAsString(); 5227243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 5228243791Sdim "{\n\t" + utostr(NumMethods) + "\n"; 5229243791Sdim 5230243791Sdim // Output instance methods declared in this protocol. 5231243791Sdim for (ObjCProtocolDecl::instmeth_iterator 5232243791Sdim I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 5233243791Sdim I != E; ++I) { 5234243791Sdim if (I == PDecl->instmeth_begin()) 5235243791Sdim Result += "\t ,{{(struct objc_selector *)\""; 5236243791Sdim else 5237243791Sdim Result += "\t ,{(struct objc_selector *)\""; 5238243791Sdim Result += (*I)->getSelector().getAsString(); 5239243791Sdim std::string MethodTypeString; 5240243791Sdim Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); 5241243791Sdim Result += "\", \""; 5242243791Sdim Result += MethodTypeString; 5243243791Sdim Result += "\"}\n"; 5244243791Sdim } 5245243791Sdim Result += "\t }\n};\n"; 5246243791Sdim } 5247243791Sdim 5248243791Sdim // Output class methods declared in this protocol. 5249243791Sdim unsigned NumMethods = std::distance(PDecl->classmeth_begin(), 5250243791Sdim PDecl->classmeth_end()); 5251243791Sdim if (NumMethods > 0) { 5252243791Sdim /* struct _objc_protocol_method_list { 5253243791Sdim int protocol_method_count; 5254243791Sdim struct protocol_methods protocols[]; 5255243791Sdim } 5256243791Sdim */ 5257243791Sdim Result += "\nstatic struct {\n"; 5258243791Sdim Result += "\tint protocol_method_count;\n"; 5259243791Sdim Result += "\tstruct _protocol_methods protocol_methods["; 5260243791Sdim Result += utostr(NumMethods); 5261243791Sdim Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_"; 5262243791Sdim Result += PDecl->getNameAsString(); 5263243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5264243791Sdim "{\n\t"; 5265243791Sdim Result += utostr(NumMethods); 5266243791Sdim Result += "\n"; 5267243791Sdim 5268243791Sdim // Output instance methods declared in this protocol. 5269243791Sdim for (ObjCProtocolDecl::classmeth_iterator 5270243791Sdim I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 5271243791Sdim I != E; ++I) { 5272243791Sdim if (I == PDecl->classmeth_begin()) 5273243791Sdim Result += "\t ,{{(struct objc_selector *)\""; 5274243791Sdim else 5275243791Sdim Result += "\t ,{(struct objc_selector *)\""; 5276243791Sdim Result += (*I)->getSelector().getAsString(); 5277243791Sdim std::string MethodTypeString; 5278243791Sdim Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); 5279243791Sdim Result += "\", \""; 5280243791Sdim Result += MethodTypeString; 5281243791Sdim Result += "\"}\n"; 5282243791Sdim } 5283243791Sdim Result += "\t }\n};\n"; 5284243791Sdim } 5285243791Sdim 5286243791Sdim // Output: 5287243791Sdim /* struct _objc_protocol { 5288243791Sdim // Objective-C 1.0 extensions 5289243791Sdim struct _objc_protocol_extension *isa; 5290243791Sdim char *protocol_name; 5291243791Sdim struct _objc_protocol **protocol_list; 5292243791Sdim struct _objc_protocol_method_list *instance_methods; 5293243791Sdim struct _objc_protocol_method_list *class_methods; 5294243791Sdim }; 5295243791Sdim */ 5296243791Sdim static bool objc_protocol = false; 5297243791Sdim if (!objc_protocol) { 5298243791Sdim Result += "\nstruct _objc_protocol {\n"; 5299243791Sdim Result += "\tstruct _objc_protocol_extension *isa;\n"; 5300243791Sdim Result += "\tchar *protocol_name;\n"; 5301243791Sdim Result += "\tstruct _objc_protocol **protocol_list;\n"; 5302243791Sdim Result += "\tstruct _objc_protocol_method_list *instance_methods;\n"; 5303243791Sdim Result += "\tstruct _objc_protocol_method_list *class_methods;\n"; 5304243791Sdim Result += "};\n"; 5305243791Sdim 5306243791Sdim objc_protocol = true; 5307243791Sdim } 5308243791Sdim 5309243791Sdim Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_"; 5310243791Sdim Result += PDecl->getNameAsString(); 5311243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 5312243791Sdim "{\n\t0, \""; 5313243791Sdim Result += PDecl->getNameAsString(); 5314243791Sdim Result += "\", 0, "; 5315243791Sdim if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 5316243791Sdim Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; 5317243791Sdim Result += PDecl->getNameAsString(); 5318243791Sdim Result += ", "; 5319243791Sdim } 5320243791Sdim else 5321243791Sdim Result += "0, "; 5322243791Sdim if (PDecl->classmeth_begin() != PDecl->classmeth_end()) { 5323243791Sdim Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; 5324243791Sdim Result += PDecl->getNameAsString(); 5325243791Sdim Result += "\n"; 5326243791Sdim } 5327243791Sdim else 5328243791Sdim Result += "0\n"; 5329243791Sdim Result += "};\n"; 5330243791Sdim 5331243791Sdim // Mark this protocol as having been generated. 5332243791Sdim if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl())) 5333243791Sdim llvm_unreachable("protocol already synthesized"); 5334243791Sdim 5335243791Sdim} 5336243791Sdim 5337243791Sdimvoid RewriteObjCFragileABI::RewriteObjCProtocolListMetaData( 5338243791Sdim const ObjCList<ObjCProtocolDecl> &Protocols, 5339243791Sdim StringRef prefix, StringRef ClassName, 5340243791Sdim std::string &Result) { 5341243791Sdim if (Protocols.empty()) return; 5342243791Sdim 5343243791Sdim for (unsigned i = 0; i != Protocols.size(); i++) 5344243791Sdim RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result); 5345243791Sdim 5346243791Sdim // Output the top lovel protocol meta-data for the class. 5347243791Sdim /* struct _objc_protocol_list { 5348243791Sdim struct _objc_protocol_list *next; 5349243791Sdim int protocol_count; 5350243791Sdim struct _objc_protocol *class_protocols[]; 5351243791Sdim } 5352243791Sdim */ 5353243791Sdim Result += "\nstatic struct {\n"; 5354243791Sdim Result += "\tstruct _objc_protocol_list *next;\n"; 5355243791Sdim Result += "\tint protocol_count;\n"; 5356243791Sdim Result += "\tstruct _objc_protocol *class_protocols["; 5357243791Sdim Result += utostr(Protocols.size()); 5358243791Sdim Result += "];\n} _OBJC_"; 5359243791Sdim Result += prefix; 5360243791Sdim Result += "_PROTOCOLS_"; 5361243791Sdim Result += ClassName; 5362243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5363243791Sdim "{\n\t0, "; 5364243791Sdim Result += utostr(Protocols.size()); 5365243791Sdim Result += "\n"; 5366243791Sdim 5367243791Sdim Result += "\t,{&_OBJC_PROTOCOL_"; 5368243791Sdim Result += Protocols[0]->getNameAsString(); 5369243791Sdim Result += " \n"; 5370243791Sdim 5371243791Sdim for (unsigned i = 1; i != Protocols.size(); i++) { 5372243791Sdim Result += "\t ,&_OBJC_PROTOCOL_"; 5373243791Sdim Result += Protocols[i]->getNameAsString(); 5374243791Sdim Result += "\n"; 5375243791Sdim } 5376243791Sdim Result += "\t }\n};\n"; 5377243791Sdim} 5378243791Sdim 5379243791Sdimvoid RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 5380243791Sdim std::string &Result) { 5381243791Sdim ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 5382243791Sdim 5383243791Sdim // Explicitly declared @interface's are already synthesized. 5384243791Sdim if (CDecl->isImplicitInterfaceDecl()) { 5385243791Sdim // FIXME: Implementation of a class with no @interface (legacy) does not 5386243791Sdim // produce correct synthesis as yet. 5387243791Sdim RewriteObjCInternalStruct(CDecl, Result); 5388243791Sdim } 5389243791Sdim 5390243791Sdim // Build _objc_ivar_list metadata for classes ivars if needed 5391243791Sdim unsigned NumIvars = !IDecl->ivar_empty() 5392243791Sdim ? IDecl->ivar_size() 5393243791Sdim : (CDecl ? CDecl->ivar_size() : 0); 5394243791Sdim if (NumIvars > 0) { 5395243791Sdim static bool objc_ivar = false; 5396243791Sdim if (!objc_ivar) { 5397243791Sdim /* struct _objc_ivar { 5398243791Sdim char *ivar_name; 5399243791Sdim char *ivar_type; 5400243791Sdim int ivar_offset; 5401243791Sdim }; 5402243791Sdim */ 5403243791Sdim Result += "\nstruct _objc_ivar {\n"; 5404243791Sdim Result += "\tchar *ivar_name;\n"; 5405243791Sdim Result += "\tchar *ivar_type;\n"; 5406243791Sdim Result += "\tint ivar_offset;\n"; 5407243791Sdim Result += "};\n"; 5408243791Sdim 5409243791Sdim objc_ivar = true; 5410243791Sdim } 5411243791Sdim 5412243791Sdim /* struct { 5413243791Sdim int ivar_count; 5414243791Sdim struct _objc_ivar ivar_list[nIvars]; 5415243791Sdim }; 5416243791Sdim */ 5417243791Sdim Result += "\nstatic struct {\n"; 5418243791Sdim Result += "\tint ivar_count;\n"; 5419243791Sdim Result += "\tstruct _objc_ivar ivar_list["; 5420243791Sdim Result += utostr(NumIvars); 5421243791Sdim Result += "];\n} _OBJC_INSTANCE_VARIABLES_"; 5422243791Sdim Result += IDecl->getNameAsString(); 5423243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 5424243791Sdim "{\n\t"; 5425243791Sdim Result += utostr(NumIvars); 5426243791Sdim Result += "\n"; 5427243791Sdim 5428243791Sdim ObjCInterfaceDecl::ivar_iterator IVI, IVE; 5429243791Sdim SmallVector<ObjCIvarDecl *, 8> IVars; 5430243791Sdim if (!IDecl->ivar_empty()) { 5431243791Sdim for (ObjCInterfaceDecl::ivar_iterator 5432243791Sdim IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); 5433243791Sdim IV != IVEnd; ++IV) 5434243791Sdim IVars.push_back(*IV); 5435243791Sdim IVI = IDecl->ivar_begin(); 5436243791Sdim IVE = IDecl->ivar_end(); 5437243791Sdim } else { 5438243791Sdim IVI = CDecl->ivar_begin(); 5439243791Sdim IVE = CDecl->ivar_end(); 5440243791Sdim } 5441243791Sdim Result += "\t,{{\""; 5442243791Sdim Result += IVI->getNameAsString(); 5443243791Sdim Result += "\", \""; 5444243791Sdim std::string TmpString, StrEncoding; 5445243791Sdim Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI); 5446243791Sdim QuoteDoublequotes(TmpString, StrEncoding); 5447243791Sdim Result += StrEncoding; 5448243791Sdim Result += "\", "; 5449243791Sdim RewriteIvarOffsetComputation(*IVI, Result); 5450243791Sdim Result += "}\n"; 5451243791Sdim for (++IVI; IVI != IVE; ++IVI) { 5452243791Sdim Result += "\t ,{\""; 5453243791Sdim Result += IVI->getNameAsString(); 5454243791Sdim Result += "\", \""; 5455243791Sdim std::string TmpString, StrEncoding; 5456243791Sdim Context->getObjCEncodingForType(IVI->getType(), TmpString, *IVI); 5457243791Sdim QuoteDoublequotes(TmpString, StrEncoding); 5458243791Sdim Result += StrEncoding; 5459243791Sdim Result += "\", "; 5460243791Sdim RewriteIvarOffsetComputation(*IVI, Result); 5461243791Sdim Result += "}\n"; 5462243791Sdim } 5463243791Sdim 5464243791Sdim Result += "\t }\n};\n"; 5465243791Sdim } 5466243791Sdim 5467243791Sdim // Build _objc_method_list for class's instance methods if needed 5468243791Sdim SmallVector<ObjCMethodDecl *, 32> 5469243791Sdim InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 5470243791Sdim 5471243791Sdim // If any of our property implementations have associated getters or 5472243791Sdim // setters, produce metadata for them as well. 5473243791Sdim for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 5474243791Sdim PropEnd = IDecl->propimpl_end(); 5475243791Sdim Prop != PropEnd; ++Prop) { 5476243791Sdim if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 5477243791Sdim continue; 5478243791Sdim if (!Prop->getPropertyIvarDecl()) 5479243791Sdim continue; 5480243791Sdim ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 5481243791Sdim if (!PD) 5482243791Sdim continue; 5483243791Sdim if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 5484243791Sdim if (!Getter->isDefined()) 5485243791Sdim InstanceMethods.push_back(Getter); 5486243791Sdim if (PD->isReadOnly()) 5487243791Sdim continue; 5488243791Sdim if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 5489243791Sdim if (!Setter->isDefined()) 5490243791Sdim InstanceMethods.push_back(Setter); 5491243791Sdim } 5492243791Sdim RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 5493243791Sdim true, "", IDecl->getName(), Result); 5494243791Sdim 5495243791Sdim // Build _objc_method_list for class's class methods if needed 5496243791Sdim RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 5497243791Sdim false, "", IDecl->getName(), Result); 5498243791Sdim 5499243791Sdim // Protocols referenced in class declaration? 5500243791Sdim RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), 5501243791Sdim "CLASS", CDecl->getName(), Result); 5502243791Sdim 5503243791Sdim // Declaration of class/meta-class metadata 5504243791Sdim /* struct _objc_class { 5505243791Sdim struct _objc_class *isa; // or const char *root_class_name when metadata 5506243791Sdim const char *super_class_name; 5507243791Sdim char *name; 5508243791Sdim long version; 5509243791Sdim long info; 5510243791Sdim long instance_size; 5511243791Sdim struct _objc_ivar_list *ivars; 5512243791Sdim struct _objc_method_list *methods; 5513243791Sdim struct objc_cache *cache; 5514243791Sdim struct objc_protocol_list *protocols; 5515243791Sdim const char *ivar_layout; 5516243791Sdim struct _objc_class_ext *ext; 5517243791Sdim }; 5518243791Sdim */ 5519243791Sdim static bool objc_class = false; 5520243791Sdim if (!objc_class) { 5521243791Sdim Result += "\nstruct _objc_class {\n"; 5522243791Sdim Result += "\tstruct _objc_class *isa;\n"; 5523243791Sdim Result += "\tconst char *super_class_name;\n"; 5524243791Sdim Result += "\tchar *name;\n"; 5525243791Sdim Result += "\tlong version;\n"; 5526243791Sdim Result += "\tlong info;\n"; 5527243791Sdim Result += "\tlong instance_size;\n"; 5528243791Sdim Result += "\tstruct _objc_ivar_list *ivars;\n"; 5529243791Sdim Result += "\tstruct _objc_method_list *methods;\n"; 5530243791Sdim Result += "\tstruct objc_cache *cache;\n"; 5531243791Sdim Result += "\tstruct _objc_protocol_list *protocols;\n"; 5532243791Sdim Result += "\tconst char *ivar_layout;\n"; 5533243791Sdim Result += "\tstruct _objc_class_ext *ext;\n"; 5534243791Sdim Result += "};\n"; 5535243791Sdim objc_class = true; 5536243791Sdim } 5537243791Sdim 5538243791Sdim // Meta-class metadata generation. 5539243791Sdim ObjCInterfaceDecl *RootClass = 0; 5540243791Sdim ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); 5541243791Sdim while (SuperClass) { 5542243791Sdim RootClass = SuperClass; 5543243791Sdim SuperClass = SuperClass->getSuperClass(); 5544243791Sdim } 5545243791Sdim SuperClass = CDecl->getSuperClass(); 5546243791Sdim 5547243791Sdim Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; 5548243791Sdim Result += CDecl->getNameAsString(); 5549243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 5550243791Sdim "{\n\t(struct _objc_class *)\""; 5551243791Sdim Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString()); 5552243791Sdim Result += "\""; 5553243791Sdim 5554243791Sdim if (SuperClass) { 5555243791Sdim Result += ", \""; 5556243791Sdim Result += SuperClass->getNameAsString(); 5557243791Sdim Result += "\", \""; 5558243791Sdim Result += CDecl->getNameAsString(); 5559243791Sdim Result += "\""; 5560243791Sdim } 5561243791Sdim else { 5562243791Sdim Result += ", 0, \""; 5563243791Sdim Result += CDecl->getNameAsString(); 5564243791Sdim Result += "\""; 5565243791Sdim } 5566243791Sdim // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. 5567243791Sdim // 'info' field is initialized to CLS_META(2) for metaclass 5568243791Sdim Result += ", 0,2, sizeof(struct _objc_class), 0"; 5569243791Sdim if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 5570243791Sdim Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; 5571243791Sdim Result += IDecl->getNameAsString(); 5572243791Sdim Result += "\n"; 5573243791Sdim } 5574243791Sdim else 5575243791Sdim Result += ", 0\n"; 5576243791Sdim if (CDecl->protocol_begin() != CDecl->protocol_end()) { 5577243791Sdim Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; 5578243791Sdim Result += CDecl->getNameAsString(); 5579243791Sdim Result += ",0,0\n"; 5580243791Sdim } 5581243791Sdim else 5582243791Sdim Result += "\t,0,0,0,0\n"; 5583243791Sdim Result += "};\n"; 5584243791Sdim 5585243791Sdim // class metadata generation. 5586243791Sdim Result += "\nstatic struct _objc_class _OBJC_CLASS_"; 5587243791Sdim Result += CDecl->getNameAsString(); 5588243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= " 5589243791Sdim "{\n\t&_OBJC_METACLASS_"; 5590243791Sdim Result += CDecl->getNameAsString(); 5591243791Sdim if (SuperClass) { 5592243791Sdim Result += ", \""; 5593243791Sdim Result += SuperClass->getNameAsString(); 5594243791Sdim Result += "\", \""; 5595243791Sdim Result += CDecl->getNameAsString(); 5596243791Sdim Result += "\""; 5597243791Sdim } 5598243791Sdim else { 5599243791Sdim Result += ", 0, \""; 5600243791Sdim Result += CDecl->getNameAsString(); 5601243791Sdim Result += "\""; 5602243791Sdim } 5603243791Sdim // 'info' field is initialized to CLS_CLASS(1) for class 5604243791Sdim Result += ", 0,1"; 5605243791Sdim if (!ObjCSynthesizedStructs.count(CDecl)) 5606243791Sdim Result += ",0"; 5607243791Sdim else { 5608243791Sdim // class has size. Must synthesize its size. 5609243791Sdim Result += ",sizeof(struct "; 5610243791Sdim Result += CDecl->getNameAsString(); 5611243791Sdim if (LangOpts.MicrosoftExt) 5612243791Sdim Result += "_IMPL"; 5613243791Sdim Result += ")"; 5614243791Sdim } 5615243791Sdim if (NumIvars > 0) { 5616243791Sdim Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_"; 5617243791Sdim Result += CDecl->getNameAsString(); 5618243791Sdim Result += "\n\t"; 5619243791Sdim } 5620243791Sdim else 5621243791Sdim Result += ",0"; 5622243791Sdim if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 5623243791Sdim Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; 5624243791Sdim Result += CDecl->getNameAsString(); 5625243791Sdim Result += ", 0\n\t"; 5626243791Sdim } 5627243791Sdim else 5628243791Sdim Result += ",0,0"; 5629243791Sdim if (CDecl->protocol_begin() != CDecl->protocol_end()) { 5630243791Sdim Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; 5631243791Sdim Result += CDecl->getNameAsString(); 5632243791Sdim Result += ", 0,0\n"; 5633243791Sdim } 5634243791Sdim else 5635243791Sdim Result += ",0,0,0\n"; 5636243791Sdim Result += "};\n"; 5637243791Sdim} 5638243791Sdim 5639243791Sdimvoid RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) { 5640243791Sdim int ClsDefCount = ClassImplementation.size(); 5641243791Sdim int CatDefCount = CategoryImplementation.size(); 5642243791Sdim 5643243791Sdim // For each implemented class, write out all its meta data. 5644243791Sdim for (int i = 0; i < ClsDefCount; i++) 5645243791Sdim RewriteObjCClassMetaData(ClassImplementation[i], Result); 5646243791Sdim 5647243791Sdim // For each implemented category, write out all its meta data. 5648243791Sdim for (int i = 0; i < CatDefCount; i++) 5649243791Sdim RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); 5650243791Sdim 5651243791Sdim // Write objc_symtab metadata 5652243791Sdim /* 5653243791Sdim struct _objc_symtab 5654243791Sdim { 5655243791Sdim long sel_ref_cnt; 5656243791Sdim SEL *refs; 5657243791Sdim short cls_def_cnt; 5658243791Sdim short cat_def_cnt; 5659243791Sdim void *defs[cls_def_cnt + cat_def_cnt]; 5660243791Sdim }; 5661243791Sdim */ 5662243791Sdim 5663243791Sdim Result += "\nstruct _objc_symtab {\n"; 5664243791Sdim Result += "\tlong sel_ref_cnt;\n"; 5665243791Sdim Result += "\tSEL *refs;\n"; 5666243791Sdim Result += "\tshort cls_def_cnt;\n"; 5667243791Sdim Result += "\tshort cat_def_cnt;\n"; 5668243791Sdim Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n"; 5669243791Sdim Result += "};\n\n"; 5670243791Sdim 5671243791Sdim Result += "static struct _objc_symtab " 5672243791Sdim "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n"; 5673243791Sdim Result += "\t0, 0, " + utostr(ClsDefCount) 5674243791Sdim + ", " + utostr(CatDefCount) + "\n"; 5675243791Sdim for (int i = 0; i < ClsDefCount; i++) { 5676243791Sdim Result += "\t,&_OBJC_CLASS_"; 5677243791Sdim Result += ClassImplementation[i]->getNameAsString(); 5678243791Sdim Result += "\n"; 5679243791Sdim } 5680243791Sdim 5681243791Sdim for (int i = 0; i < CatDefCount; i++) { 5682243791Sdim Result += "\t,&_OBJC_CATEGORY_"; 5683243791Sdim Result += CategoryImplementation[i]->getClassInterface()->getNameAsString(); 5684243791Sdim Result += "_"; 5685243791Sdim Result += CategoryImplementation[i]->getNameAsString(); 5686243791Sdim Result += "\n"; 5687243791Sdim } 5688243791Sdim 5689243791Sdim Result += "};\n\n"; 5690243791Sdim 5691243791Sdim // Write objc_module metadata 5692243791Sdim 5693243791Sdim /* 5694243791Sdim struct _objc_module { 5695243791Sdim long version; 5696243791Sdim long size; 5697243791Sdim const char *name; 5698243791Sdim struct _objc_symtab *symtab; 5699243791Sdim } 5700243791Sdim */ 5701243791Sdim 5702243791Sdim Result += "\nstruct _objc_module {\n"; 5703243791Sdim Result += "\tlong version;\n"; 5704243791Sdim Result += "\tlong size;\n"; 5705243791Sdim Result += "\tconst char *name;\n"; 5706243791Sdim Result += "\tstruct _objc_symtab *symtab;\n"; 5707243791Sdim Result += "};\n\n"; 5708243791Sdim Result += "static struct _objc_module " 5709243791Sdim "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n"; 5710243791Sdim Result += "\t" + utostr(OBJC_ABI_VERSION) + 5711243791Sdim ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n"; 5712243791Sdim Result += "};\n\n"; 5713243791Sdim 5714243791Sdim if (LangOpts.MicrosoftExt) { 5715243791Sdim if (ProtocolExprDecls.size()) { 5716243791Sdim Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n"; 5717243791Sdim Result += "#pragma data_seg(push, \".objc_protocol$B\")\n"; 5718243791Sdim for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 5719243791Sdim E = ProtocolExprDecls.end(); I != E; ++I) { 5720243791Sdim Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_"; 5721243791Sdim Result += (*I)->getNameAsString(); 5722243791Sdim Result += " = &_OBJC_PROTOCOL_"; 5723243791Sdim Result += (*I)->getNameAsString(); 5724243791Sdim Result += ";\n"; 5725243791Sdim } 5726243791Sdim Result += "#pragma data_seg(pop)\n\n"; 5727243791Sdim } 5728243791Sdim Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n"; 5729243791Sdim Result += "#pragma data_seg(push, \".objc_module_info$B\")\n"; 5730243791Sdim Result += "static struct _objc_module *_POINTER_OBJC_MODULES = "; 5731243791Sdim Result += "&_OBJC_MODULES;\n"; 5732243791Sdim Result += "#pragma data_seg(pop)\n\n"; 5733243791Sdim } 5734243791Sdim} 5735243791Sdim 5736243791Sdim/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category 5737243791Sdim/// implementation. 5738243791Sdimvoid RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, 5739243791Sdim std::string &Result) { 5740243791Sdim ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 5741243791Sdim // Find category declaration for this implementation. 5742249423Sdim ObjCCategoryDecl *CDecl 5743249423Sdim = ClassDecl->FindCategoryDeclaration(IDecl->getIdentifier()); 5744243791Sdim 5745243791Sdim std::string FullCategoryName = ClassDecl->getNameAsString(); 5746243791Sdim FullCategoryName += '_'; 5747243791Sdim FullCategoryName += IDecl->getNameAsString(); 5748243791Sdim 5749243791Sdim // Build _objc_method_list for class's instance methods if needed 5750243791Sdim SmallVector<ObjCMethodDecl *, 32> 5751243791Sdim InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 5752243791Sdim 5753243791Sdim // If any of our property implementations have associated getters or 5754243791Sdim // setters, produce metadata for them as well. 5755243791Sdim for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 5756243791Sdim PropEnd = IDecl->propimpl_end(); 5757243791Sdim Prop != PropEnd; ++Prop) { 5758243791Sdim if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 5759243791Sdim continue; 5760243791Sdim if (!Prop->getPropertyIvarDecl()) 5761243791Sdim continue; 5762243791Sdim ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 5763243791Sdim if (!PD) 5764243791Sdim continue; 5765243791Sdim if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 5766243791Sdim InstanceMethods.push_back(Getter); 5767243791Sdim if (PD->isReadOnly()) 5768243791Sdim continue; 5769243791Sdim if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 5770243791Sdim InstanceMethods.push_back(Setter); 5771243791Sdim } 5772243791Sdim RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 5773243791Sdim true, "CATEGORY_", FullCategoryName.c_str(), 5774243791Sdim Result); 5775243791Sdim 5776243791Sdim // Build _objc_method_list for class's class methods if needed 5777243791Sdim RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 5778243791Sdim false, "CATEGORY_", FullCategoryName.c_str(), 5779243791Sdim Result); 5780243791Sdim 5781243791Sdim // Protocols referenced in class declaration? 5782243791Sdim // Null CDecl is case of a category implementation with no category interface 5783243791Sdim if (CDecl) 5784243791Sdim RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", 5785243791Sdim FullCategoryName, Result); 5786243791Sdim /* struct _objc_category { 5787243791Sdim char *category_name; 5788243791Sdim char *class_name; 5789243791Sdim struct _objc_method_list *instance_methods; 5790243791Sdim struct _objc_method_list *class_methods; 5791243791Sdim struct _objc_protocol_list *protocols; 5792243791Sdim // Objective-C 1.0 extensions 5793243791Sdim uint32_t size; // sizeof (struct _objc_category) 5794243791Sdim struct _objc_property_list *instance_properties; // category's own 5795243791Sdim // @property decl. 5796243791Sdim }; 5797243791Sdim */ 5798243791Sdim 5799243791Sdim static bool objc_category = false; 5800243791Sdim if (!objc_category) { 5801243791Sdim Result += "\nstruct _objc_category {\n"; 5802243791Sdim Result += "\tchar *category_name;\n"; 5803243791Sdim Result += "\tchar *class_name;\n"; 5804243791Sdim Result += "\tstruct _objc_method_list *instance_methods;\n"; 5805243791Sdim Result += "\tstruct _objc_method_list *class_methods;\n"; 5806243791Sdim Result += "\tstruct _objc_protocol_list *protocols;\n"; 5807243791Sdim Result += "\tunsigned int size;\n"; 5808243791Sdim Result += "\tstruct _objc_property_list *instance_properties;\n"; 5809243791Sdim Result += "};\n"; 5810243791Sdim objc_category = true; 5811243791Sdim } 5812243791Sdim Result += "\nstatic struct _objc_category _OBJC_CATEGORY_"; 5813243791Sdim Result += FullCategoryName; 5814243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\""; 5815243791Sdim Result += IDecl->getNameAsString(); 5816243791Sdim Result += "\"\n\t, \""; 5817243791Sdim Result += ClassDecl->getNameAsString(); 5818243791Sdim Result += "\"\n"; 5819243791Sdim 5820243791Sdim if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 5821243791Sdim Result += "\t, (struct _objc_method_list *)" 5822243791Sdim "&_OBJC_CATEGORY_INSTANCE_METHODS_"; 5823243791Sdim Result += FullCategoryName; 5824243791Sdim Result += "\n"; 5825243791Sdim } 5826243791Sdim else 5827243791Sdim Result += "\t, 0\n"; 5828243791Sdim if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 5829243791Sdim Result += "\t, (struct _objc_method_list *)" 5830243791Sdim "&_OBJC_CATEGORY_CLASS_METHODS_"; 5831243791Sdim Result += FullCategoryName; 5832243791Sdim Result += "\n"; 5833243791Sdim } 5834243791Sdim else 5835243791Sdim Result += "\t, 0\n"; 5836243791Sdim 5837243791Sdim if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) { 5838243791Sdim Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; 5839243791Sdim Result += FullCategoryName; 5840243791Sdim Result += "\n"; 5841243791Sdim } 5842243791Sdim else 5843243791Sdim Result += "\t, 0\n"; 5844243791Sdim Result += "\t, sizeof(struct _objc_category), 0\n};\n"; 5845243791Sdim} 5846243791Sdim 5847243791Sdim// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or 5848243791Sdim/// class methods. 5849243791Sdimtemplate<typename MethodIterator> 5850243791Sdimvoid RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 5851243791Sdim MethodIterator MethodEnd, 5852243791Sdim bool IsInstanceMethod, 5853243791Sdim StringRef prefix, 5854243791Sdim StringRef ClassName, 5855243791Sdim std::string &Result) { 5856243791Sdim if (MethodBegin == MethodEnd) return; 5857243791Sdim 5858243791Sdim if (!objc_impl_method) { 5859243791Sdim /* struct _objc_method { 5860243791Sdim SEL _cmd; 5861243791Sdim char *method_types; 5862243791Sdim void *_imp; 5863243791Sdim } 5864243791Sdim */ 5865243791Sdim Result += "\nstruct _objc_method {\n"; 5866243791Sdim Result += "\tSEL _cmd;\n"; 5867243791Sdim Result += "\tchar *method_types;\n"; 5868243791Sdim Result += "\tvoid *_imp;\n"; 5869243791Sdim Result += "};\n"; 5870243791Sdim 5871243791Sdim objc_impl_method = true; 5872243791Sdim } 5873243791Sdim 5874243791Sdim // Build _objc_method_list for class's methods if needed 5875243791Sdim 5876243791Sdim /* struct { 5877243791Sdim struct _objc_method_list *next_method; 5878243791Sdim int method_count; 5879243791Sdim struct _objc_method method_list[]; 5880243791Sdim } 5881243791Sdim */ 5882243791Sdim unsigned NumMethods = std::distance(MethodBegin, MethodEnd); 5883243791Sdim Result += "\nstatic struct {\n"; 5884243791Sdim Result += "\tstruct _objc_method_list *next_method;\n"; 5885243791Sdim Result += "\tint method_count;\n"; 5886243791Sdim Result += "\tstruct _objc_method method_list["; 5887243791Sdim Result += utostr(NumMethods); 5888243791Sdim Result += "];\n} _OBJC_"; 5889243791Sdim Result += prefix; 5890243791Sdim Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; 5891243791Sdim Result += "_METHODS_"; 5892243791Sdim Result += ClassName; 5893243791Sdim Result += " __attribute__ ((used, section (\"__OBJC, __"; 5894243791Sdim Result += IsInstanceMethod ? "inst" : "cls"; 5895243791Sdim Result += "_meth\")))= "; 5896243791Sdim Result += "{\n\t0, " + utostr(NumMethods) + "\n"; 5897243791Sdim 5898243791Sdim Result += "\t,{{(SEL)\""; 5899243791Sdim Result += (*MethodBegin)->getSelector().getAsString().c_str(); 5900243791Sdim std::string MethodTypeString; 5901243791Sdim Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 5902243791Sdim Result += "\", \""; 5903243791Sdim Result += MethodTypeString; 5904243791Sdim Result += "\", (void *)"; 5905243791Sdim Result += MethodInternalNames[*MethodBegin]; 5906243791Sdim Result += "}\n"; 5907243791Sdim for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { 5908243791Sdim Result += "\t ,{(SEL)\""; 5909243791Sdim Result += (*MethodBegin)->getSelector().getAsString().c_str(); 5910243791Sdim std::string MethodTypeString; 5911243791Sdim Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 5912243791Sdim Result += "\", \""; 5913243791Sdim Result += MethodTypeString; 5914243791Sdim Result += "\", (void *)"; 5915243791Sdim Result += MethodInternalNames[*MethodBegin]; 5916243791Sdim Result += "}\n"; 5917243791Sdim } 5918243791Sdim Result += "\t }\n};\n"; 5919243791Sdim} 5920243791Sdim 5921243791SdimStmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { 5922243791Sdim SourceRange OldRange = IV->getSourceRange(); 5923243791Sdim Expr *BaseExpr = IV->getBase(); 5924243791Sdim 5925243791Sdim // Rewrite the base, but without actually doing replaces. 5926243791Sdim { 5927243791Sdim DisableReplaceStmtScope S(*this); 5928243791Sdim BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr)); 5929243791Sdim IV->setBase(BaseExpr); 5930243791Sdim } 5931243791Sdim 5932243791Sdim ObjCIvarDecl *D = IV->getDecl(); 5933243791Sdim 5934243791Sdim Expr *Replacement = IV; 5935243791Sdim if (CurMethodDef) { 5936243791Sdim if (BaseExpr->getType()->isObjCObjectPointerType()) { 5937243791Sdim const ObjCInterfaceType *iFaceDecl = 5938243791Sdim dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 5939243791Sdim assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); 5940243791Sdim // lookup which class implements the instance variable. 5941243791Sdim ObjCInterfaceDecl *clsDeclared = 0; 5942243791Sdim iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 5943243791Sdim clsDeclared); 5944243791Sdim assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 5945243791Sdim 5946243791Sdim // Synthesize an explicit cast to gain access to the ivar. 5947243791Sdim std::string RecName = clsDeclared->getIdentifier()->getName(); 5948243791Sdim RecName += "_IMPL"; 5949243791Sdim IdentifierInfo *II = &Context->Idents.get(RecName); 5950243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 5951243791Sdim SourceLocation(), SourceLocation(), 5952243791Sdim II); 5953243791Sdim assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 5954243791Sdim QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 5955243791Sdim CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 5956243791Sdim CK_BitCast, 5957243791Sdim IV->getBase()); 5958243791Sdim // Don't forget the parens to enforce the proper binding. 5959243791Sdim ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(), 5960243791Sdim OldRange.getEnd(), 5961243791Sdim castExpr); 5962243791Sdim if (IV->isFreeIvar() && 5963243791Sdim declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) { 5964243791Sdim MemberExpr *ME = new (Context) MemberExpr(PE, true, D, 5965243791Sdim IV->getLocation(), 5966243791Sdim D->getType(), 5967243791Sdim VK_LValue, OK_Ordinary); 5968243791Sdim Replacement = ME; 5969243791Sdim } else { 5970243791Sdim IV->setBase(PE); 5971243791Sdim } 5972243791Sdim } 5973243791Sdim } else { // we are outside a method. 5974243791Sdim assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); 5975243791Sdim 5976243791Sdim // Explicit ivar refs need to have a cast inserted. 5977243791Sdim // FIXME: consider sharing some of this code with the code above. 5978243791Sdim if (BaseExpr->getType()->isObjCObjectPointerType()) { 5979243791Sdim const ObjCInterfaceType *iFaceDecl = 5980243791Sdim dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 5981243791Sdim // lookup which class implements the instance variable. 5982243791Sdim ObjCInterfaceDecl *clsDeclared = 0; 5983243791Sdim iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 5984243791Sdim clsDeclared); 5985243791Sdim assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 5986243791Sdim 5987243791Sdim // Synthesize an explicit cast to gain access to the ivar. 5988243791Sdim std::string RecName = clsDeclared->getIdentifier()->getName(); 5989243791Sdim RecName += "_IMPL"; 5990243791Sdim IdentifierInfo *II = &Context->Idents.get(RecName); 5991243791Sdim RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 5992243791Sdim SourceLocation(), SourceLocation(), 5993243791Sdim II); 5994243791Sdim assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 5995243791Sdim QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 5996243791Sdim CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 5997243791Sdim CK_BitCast, 5998243791Sdim IV->getBase()); 5999243791Sdim // Don't forget the parens to enforce the proper binding. 6000243791Sdim ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), 6001243791Sdim IV->getBase()->getLocEnd(), castExpr); 6002243791Sdim // Cannot delete IV->getBase(), since PE points to it. 6003243791Sdim // Replace the old base with the cast. This is important when doing 6004243791Sdim // embedded rewrites. For example, [newInv->_container addObject:0]. 6005243791Sdim IV->setBase(PE); 6006243791Sdim } 6007243791Sdim } 6008243791Sdim 6009243791Sdim ReplaceStmtWithRange(IV, Replacement, OldRange); 6010243791Sdim return Replacement; 6011243791Sdim} 6012