RewriteObjC.cpp revision 88914801a4d73e321c6f74f97df7d7b11c298bc6
1b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroff//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===// 277cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 377cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// The LLVM Compiler Infrastructure 477cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 777cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 877cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner//===----------------------------------------------------------------------===// 977cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 1077cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// Hacks and fun related to the code rewriter. 1177cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 1277cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner//===----------------------------------------------------------------------===// 1377cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 149b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Rewrite/ASTConsumers.h" 158a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner#include "clang/Rewrite/Rewriter.h" 1677cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner#include "clang/AST/AST.h" 1777cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner#include "clang/AST/ASTConsumer.h" 188599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff#include "clang/AST/ParentMap.h" 198a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner#include "clang/Basic/SourceManager.h" 20ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff#include "clang/Basic/IdentifierTable.h" 210750618b0beacdc9b0a9e210a661e4746823ced7Chris Lattner#include "clang/Basic/Diagnostic.h" 2226de4655a38b899e0f0dcef4175032175854d1cfChris Lattner#include "clang/Lex/Lexer.h" 236cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/MemoryBuffer.h" 246cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/raw_ostream.h" 25158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner#include "llvm/ADT/StringExtras.h" 2626e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian#include "llvm/ADT/SmallPtrSet.h" 27a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek#include "llvm/ADT/OwningPtr.h" 28ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian#include "llvm/ADT/DenseSet.h" 2972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian 3077cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattnerusing namespace clang; 31158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattnerusing llvm::utostr; 3277cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 3377cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattnernamespace { 34b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroff class RewriteObjC : public ASTConsumer { 3573e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian enum { 3659b173d81b05b7d10cec8b06b3fd843230ef628cNico Weber BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 3773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian block, ... */ 3873e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 3973e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the 4073e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian __block variable */ 4159b173d81b05b7d10cec8b06b3fd843230ef628cNico Weber BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 4273e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian helpers */ 4359b173d81b05b7d10cec8b06b3fd843230ef628cNico Weber BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 4473e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian support routines */ 4573e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_BYREF_CURRENT_MAX = 256 4673e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian }; 4773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian 4873e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian enum { 4973e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_NEEDS_FREE = (1 << 24), 5073e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_COPY_DISPOSE = (1 << 25), 5173e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_CXX_OBJ = (1 << 26), 5273e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_IS_GC = (1 << 27), 5373e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_IS_GLOBAL = (1 << 28), 5473e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_DESCRIPTOR = (1 << 29) 5573e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian }; 5673e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian 572c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner Rewriter Rewrite; 58e365c50a21cb02e0219433db0c4461566ad4a597Chris Lattner Diagnostic &Diags; 594f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff const LangOptions &LangOpts; 60f69cc5d6606fc65a76e3acd6eb6e13efd0098295Steve Naroff unsigned RewriteFailedDiag; 618c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff unsigned TryFinallyContainsReturnDiag; 621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6301c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner ASTContext *Context; 6477cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner SourceManager *SM; 65ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis TranslationUnitDecl *TUDecl; 662b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID MainFileID; 6726de4655a38b899e0f0dcef4175032175854d1cfChris Lattner const char *MainFileStart, *MainFileEnd; 682c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner SourceLocation LastIncLoc; 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 705f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; 715f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; 72a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; 73fbfe82527dadb09c95609a742744d75a2322850cSteve Naroff llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; 74a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls; 75a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; 765f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Stmt *, 32> Stmts; 775f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<int, 8> ObjCBcLabelNo; 78621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Remember all the @protocol(<expr>) expressions. 79621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; 80ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian 81ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian llvm::DenseSet<uint64_t> CopyDestroyCache; 82ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian 83d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff unsigned NumObjCStringLiterals; 841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 85ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff FunctionDecl *MsgSendFunctionDecl; 86874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff FunctionDecl *MsgSendSuperFunctionDecl; 8780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendStretFunctionDecl; 8880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendSuperStretFunctionDecl; 89acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian FunctionDecl *MsgSendFpretFunctionDecl; 90ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff FunctionDecl *GetClassFunctionDecl; 919bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff FunctionDecl *GetMetaClassFunctionDecl; 92d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian FunctionDecl *GetSuperClassFunctionDecl; 93934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff FunctionDecl *SelGetUidFunctionDecl; 949698464266660346fa2da1bddc3e6404a9819b25Steve Naroff FunctionDecl *CFStringFunctionDecl; 95c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff FunctionDecl *SuperContructorFunctionDecl; 961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff // ObjC string constant support. 98248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff VarDecl *ConstantStringClassReference; 99beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff RecordDecl *NSStringRecord; 1001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 101b586cce95c69161c771f7a966383beb4fc5dd394Fariborz Jahanian // ObjC foreach break/continue generation support. 102e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian int BcLabelCount; 1031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // Needed for super. 10554055232a5ddb9529726e934301b125cb720a273Steve Naroff ObjCMethodDecl *CurMethodDef; 106874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff RecordDecl *SuperStructDecl; 107d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff RecordDecl *ConstantStringDecl; 1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff TypeDecl *ProtocolTypeDecl; 110621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QualType getProtocolType(); 1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // Needed for header files being rewritten 113b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian bool IsHeader; 1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff std::string InFileName; 1165f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner raw_ostream* OutFile; 117c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman 118c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool SilenceRewriteMacroWarning; 119f292fcf6bd5118499a830e0950429effeb373c28Fariborz Jahanian bool objc_impl_method; 120c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman 121ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff std::string Preamble; 12254055232a5ddb9529726e934301b125cb720a273Steve Naroff 12354055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block expressions. 1245f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockExpr *, 32> Blocks; 1255f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<int, 32> InnerDeclRefsCount; 1265f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockDeclRefExpr *, 32> InnerDeclRefs; 1275e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 1285f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs; 1291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13054055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block related declarations. 1315f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ValueDecl *, 8> BlockByCopyDecls; 132bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; 1335f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ValueDecl *, 8> BlockByRefDecls; 134bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; 135a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; 13654055232a5ddb9529726e934301b125cb720a273Steve Naroff llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; 1376cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls; 1386cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 13954055232a5ddb9529726e934301b125cb720a273Steve Naroff llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; 14054055232a5ddb9529726e934301b125cb720a273Steve Naroff 141c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // This maps a property to it's assignment statement. 142f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian llvm::DenseMap<Expr *, BinaryOperator *> PropSetters; 1438599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // This maps a property to it's synthesied message expression. 1448599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // This allows us to rewrite chained getters (e.g. o.a.b.c). 145f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian llvm::DenseMap<Expr *, Stmt *> PropGetters; 1461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1474c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // This maps an original source AST to it's rewritten form. This allows 1484c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // us to avoid rewriting the same node twice (which is very uncommon). 1494c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // This is needed to support some of the exotic property rewriting. 1504c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; 15115f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 15254055232a5ddb9529726e934301b125cb720a273Steve Naroff FunctionDecl *CurFunctionDef; 153abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FunctionDecl *CurFunctionDeclToDeclareForBlock; 1548e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff VarDecl *GlobalVarDecl; 1551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 156b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff bool DisableReplaceStmt; 1571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1587e7492442f32e3abbe246f6bb35568b044c1188bNick Lewycky static const int OBJC_ABI_VERSION = 7; 15977cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner public: 160e3a6198400453c0d9623207718e4942f7c111f87Ted Kremenek virtual void Initialize(ASTContext &context); 161e3a6198400453c0d9623207718e4942f7c111f87Ted Kremenek 162f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Top Level Driver code. 163682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner virtual void HandleTopLevelDecl(DeclGroupRef D) { 16495ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 16595ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian if (isa<ObjCClassDecl>((*I))) { 16695ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian RewriteForwardClassDecl(D); 16795ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian break; 16895ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian } 169682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner HandleTopLevelSingleDecl(*I); 17095ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian } 171682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner } 172682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner void HandleTopLevelSingleDecl(Decl *D); 1732c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner void HandleDeclInMainFile(Decl *D); 1745f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner RewriteObjC(std::string inFile, raw_ostream *OS, 175c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman Diagnostic &D, const LangOptions &LOpts, 176c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool silenceMacroWarn); 177e452e0ffc81c6c3d79680f552f2623e6cf0956d7Ted Kremenek 178e452e0ffc81c6c3d79680f552f2623e6cf0956d7Ted Kremenek ~RewriteObjC() {} 1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 180dacbc5d46aaeea817742b8c76c987b87d2490c85Chris Lattner virtual void HandleTranslationUnit(ASTContext &C); 1811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18288906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanian void ReplaceStmt(Stmt *Old, Stmt *New) { 1834c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff Stmt *ReplacingStmt = ReplacedNodes[Old]; 1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1854c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff if (ReplacingStmt) 1864c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff return; // We can't rewrite the same node twice. 1874c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff 188b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (DisableReplaceStmt) 189b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; // Used when rewriting the assignment of a property setter. 190b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 191f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner // If replacement succeeded or warning disabled return with no warning. 19288906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanian if (!Rewrite.ReplaceStmt(Old, New)) { 1934c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff ReplacedNodes[Old] = New; 1944c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff return; 1954c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff } 1964c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff if (SilenceRewriteMacroWarning) 197dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner return; 1980a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 1990a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner << Old->getSourceRange(); 200dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner } 201b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 202b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { 2037e7492442f32e3abbe246f6bb35568b044c1188bNick Lewycky // Measure the old text. 204b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff int Size = Rewrite.getRangeSize(SrcRange); 205b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (Size == -1) { 206b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 207b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff << Old->getSourceRange(); 208b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 209b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 210b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // Get the new text. 211b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff std::string SStr; 212b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff llvm::raw_string_ostream S(SStr); 213e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts)); 214b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff const std::string &Str = S.str(); 215b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 216b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // If replacement succeeded or warning disabled return with no warning. 217d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) { 218b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff ReplacedNodes[Old] = New; 219b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 220b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 221b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (SilenceRewriteMacroWarning) 222b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 223b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 224b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff << Old->getSourceRange(); 225b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 226b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 2275f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner void InsertText(SourceLocation Loc, StringRef Str, 228ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff bool InsertAfter = true) { 229aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner // If insertion succeeded or warning disabled return with no warning. 230d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer if (!Rewrite.InsertText(Loc, Str, InsertAfter) || 231f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner SilenceRewriteMacroWarning) 232f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner return; 2331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 234f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 235f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner } 2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 237aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner void ReplaceText(SourceLocation Start, unsigned OrigLength, 2385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Str) { 239aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner // If removal succeeded or warning disabled return with no warning. 240d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer if (!Rewrite.ReplaceText(Start, OrigLength, Str) || 241aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner SilenceRewriteMacroWarning) 242aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner return; 2431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 244aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); 245aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner } 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 247f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Syntactic Rewriting. 248452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian void RewriteInclude(); 24995ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian void RewriteForwardClassDecl(DeclGroupRef D); 250a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG); 251a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian void RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, 252a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const std::string &typedefString); 253a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian 254a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 255a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCImplementationDecl *IMD, 256a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCCategoryImplDecl *CID); 257a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); 2584afa39deaa245592977136d367251ee2c173dd8dDouglas Gregor void RewriteImplementationDecl(Decl *Dcl); 2592d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 2602d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian ObjCMethodDecl *MDecl, std::string &ResultStr); 2617c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian void RewriteTypeIntoString(QualType T, std::string &ResultStr, 2627c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *&FPRetType); 263a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian void RewriteByRefString(std::string &ResultStr, const std::string &Name, 2641e8011e2fcddc4a638d210ec2dcd21adcf7b1763Fariborz Jahanian ValueDecl *VD, bool def=false); 265a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); 266a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); 267a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl); 268a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteMethodDeclaration(ObjCMethodDecl *Method); 2696327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff void RewriteProperty(ObjCPropertyDecl *prop); 27009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff void RewriteFunctionDecl(FunctionDecl *FD); 271fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar void RewriteBlockPointerType(std::string& Str, QualType Type); 272fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD); 273abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); 274a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); 2754c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian void RewriteTypeOfDecl(VarDecl *VD); 2764f95b750534f2111f28434b282bcbd5656002816Steve Naroff void RewriteObjCQualifiedInterfaceTypes(Expr *E); 277d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff bool needToScanForQualifiers(QualType T); 278874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType getSuperStructType(); 279d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff QualType getConstantStringStructType(); 2801f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType convertFunctionTypeOfBlocks(const FunctionType *FT); 281baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); 2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 283f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Expression Rewriting. 284f3473a7e48dfaaa88f58dd9304856e16754f9b1cSteve Naroff Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); 285c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff void CollectPropertySetters(Stmt *S); 2861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2878599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff Stmt *CurrentBody; 2888599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff ParentMap *PropParentMap; // created lazily. 2891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 290e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); 2912b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart, 2922b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian bool &replaced); 2932b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced); 294f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Stmt *RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr); 295f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Stmt *RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt, 296b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff SourceRange SrcRange); 297b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); 298e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); 299beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); 30036ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); 301b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void WarnAboutReturnGotoStmts(Stmt *S); 302b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void HasReturnStmts(Stmt *S, bool &hasReturns); 303b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void RewriteTryReturnStmts(Stmt *S); 304b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void RewriteSyncReturnStmts(Stmt *S, std::string buf); 305a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); 306a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); 307a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); 308338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 309338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner SourceLocation OrigEnd); 31042f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanian bool IsDeclStmtInForeachHeader(DeclStmt *DS); 3111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 3121d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Expr **args, unsigned nargs, 3131d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation StartLoc=SourceLocation(), 3141d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc=SourceLocation()); 3151d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, 3161d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation StartLoc=SourceLocation(), 3171d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc=SourceLocation()); 318e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmt *RewriteBreakStmt(BreakStmt *S); 319e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmt *RewriteContinueStmt(ContinueStmt *S); 32033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian void SynthCountByEnumWithState(std::string &buf); 3211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32209b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff void SynthMsgSendFunctionDecl(); 323874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff void SynthMsgSendSuperFunctionDecl(); 32480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian void SynthMsgSendStretFunctionDecl(); 325acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian void SynthMsgSendFpretFunctionDecl(); 32680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian void SynthMsgSendSuperStretFunctionDecl(); 32709b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff void SynthGetClassFunctionDecl(); 3289bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff void SynthGetMetaClassFunctionDecl(); 329d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian void SynthGetSuperClassFunctionDecl(); 330a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian void SynthSelGetUidFunctionDecl(); 331c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff void SynthSuperContructorFunctionDecl(); 3321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 333f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Metadata emission. 334a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 335ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian std::string &Result); 3361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 337a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 338ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian std::string &Result); 3391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 340653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor template<typename MethodIterator> 341653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 342653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor MethodIterator MethodEnd, 3438e991ba2e256e56959a65a049e161aa30b3c0decFariborz Jahanian bool IsInstanceMethod, 3445f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef prefix, 3455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef ClassName, 346158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner std::string &Result); 3471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 348621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 3495f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef prefix, 3505f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef ClassName, 351621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string &Result); 352621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, 3535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef prefix, 3545f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef ClassName, 355621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string &Result); 356a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, 35726e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result); 3582d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian void SynthesizeIvarOffsetComputation(ObjCIvarDecl *ivar, 35926e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result); 360ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff void RewriteImplementations(); 361ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff void SynthesizeMetaDataIntoBuffer(std::string &Result); 3621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36354055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block rewriting. 3641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); 36554055232a5ddb9529726e934301b125cb720a273Steve Naroff void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); 3661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36754055232a5ddb9529726e934301b125cb720a273Steve Naroff void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); 36854055232a5ddb9529726e934301b125cb720a273Steve Naroff void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); 3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Block specific rewrite rules. 37154055232a5ddb9529726e934301b125cb720a273Steve Naroff void RewriteBlockPointerDecl(NamedDecl *VD); 37252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian void RewriteByRefVar(VarDecl *VD); 373ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); 374f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian Stmt *RewriteBlockDeclRefExpr(Expr *VD); 3756cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); 37654055232a5ddb9529726e934301b125cb720a273Steve Naroff void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); 3771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 3795f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef funcName, std::string Tag); 3801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string SynthesizeBlockFunc(BlockExpr *CE, int i, 3815f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef funcName, std::string Tag); 38201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string SynthesizeBlockImpl(BlockExpr *CE, 38301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string Tag, std::string Desc); 38401aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string SynthesizeBlockDescriptor(std::string DescTag, 38501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string ImplTag, 3865f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner int i, StringRef funcName, 38701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff unsigned hasCopy); 3888a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); 38954055232a5ddb9529726e934301b125cb720a273Steve Naroff void SynthesizeBlockLiterals(SourceLocation FunLocStart, 3905f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef FunName); 3913d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff void RewriteRecordBody(RecordDecl *RD); 3921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39354055232a5ddb9529726e934301b125cb720a273Steve Naroff void CollectBlockDeclRefInfo(BlockExpr *Exp); 39454055232a5ddb9529726e934301b125cb720a273Steve Naroff void GetBlockDeclRefExprs(Stmt *S); 3955e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian void GetInnerBlockDeclRefExprs(Stmt *S, 3965f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs, 39772952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts); 3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39954055232a5ddb9529726e934301b125cb720a273Steve Naroff // We avoid calling Type::isBlockPointerType(), since it operates on the 40054055232a5ddb9529726e934301b125cb720a273Steve Naroff // canonical type. We only care if the top-level type is a closure pointer. 4018189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek bool isTopLevelBlockPointerType(QualType T) { 4028189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return isa<BlockPointerType>(T); 4038189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek } 4041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4054fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// convertBlockPointerToFunctionPointer - Converts a block-pointer type 4064fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// to a function pointer type and upon success, returns true; false 4074fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// otherwise. 4084fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian bool convertBlockPointerToFunctionPointer(QualType &T) { 4094fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (isTopLevelBlockPointerType(T)) { 4104fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian const BlockPointerType *BPT = T->getAs<BlockPointerType>(); 4114fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian T = Context->getPointerType(BPT->getPointeeType()); 4124fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian return true; 4134fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian } 4144fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian return false; 4154fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian } 4164fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian 4178188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian void convertToUnqualifiedObjCType(QualType &T) { 4188188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian if (T->isObjCQualifiedIdType()) 4198188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian T = Context->getObjCIdType(); 4208188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian else if (T->isObjCQualifiedClassType()) 4218188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian T = Context->getObjCClassType(); 4228188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian else if (T->isObjCObjectPointerType() && 4238188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian T->getPointeeType()->isObjCQualifiedInterfaceType()) 4248188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian T = Context->getObjCIdType(); 4258188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian } 4268188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian 42754055232a5ddb9529726e934301b125cb720a273Steve Naroff // FIXME: This predicate seems like it would be useful to add to ASTContext. 42854055232a5ddb9529726e934301b125cb720a273Steve Naroff bool isObjCType(QualType T) { 42954055232a5ddb9529726e934301b125cb720a273Steve Naroff if (!LangOpts.ObjC1 && !LangOpts.ObjC2) 43054055232a5ddb9529726e934301b125cb720a273Steve Naroff return false; 4311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 43254055232a5ddb9529726e934301b125cb720a273Steve Naroff QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); 4331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 43454055232a5ddb9529726e934301b125cb720a273Steve Naroff if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || 43554055232a5ddb9529726e934301b125cb720a273Steve Naroff OCT == Context->getCanonicalType(Context->getObjCClassType())) 43654055232a5ddb9529726e934301b125cb720a273Steve Naroff return true; 4371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4386217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (const PointerType *PT = OCT->getAs<PointerType>()) { 4391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (isa<ObjCInterfaceType>(PT->getPointeeType()) || 440d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff PT->getPointeeType()->isObjCQualifiedIdType()) 44154055232a5ddb9529726e934301b125cb720a273Steve Naroff return true; 44254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 44354055232a5ddb9529726e934301b125cb720a273Steve Naroff return false; 44454055232a5ddb9529726e934301b125cb720a273Steve Naroff } 44554055232a5ddb9529726e934301b125cb720a273Steve Naroff bool PointerTypeTakesAnyBlockArguments(QualType QT); 446e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian bool PointerTypeTakesAnyObjCQualifiedType(QualType QT); 4478189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek void GetExtentOfArgList(const char *Name, const char *&LParen, 4488189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek const char *&RParen); 449b2f9e516327310d95840d442416084508f80c183Steve Naroff void RewriteCastExpr(CStyleCastExpr *CE); 4501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4515f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); 4525e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian Stmt *SynthBlockInitExpr(BlockExpr *Exp, 4535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs); 4541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 455621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff void QuoteDoublequotes(std::string &From, std::string &To) { 4561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (unsigned i = 0; i < From.length(); i++) { 457621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (From[i] == '"') 458621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff To += "\\\""; 459621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 460621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff To += From[i]; 461621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 462621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 463e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall 464e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getSimpleFunctionType(QualType result, 465e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall const QualType *args, 466e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall unsigned numArgs, 467e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall bool variadic = false) { 46888914801a4d73e321c6f74f97df7d7b11c298bc6Fariborz Jahanian if (result == Context->getObjCInstanceType()) 46988914801a4d73e321c6f74f97df7d7b11c298bc6Fariborz Jahanian result = Context->getObjCIdType(); 470e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall FunctionProtoType::ExtProtoInfo fpi; 471e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall fpi.Variadic = variadic; 472e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall return Context->getFunctionType(result, args, numArgs, fpi); 473e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall } 47477cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner }; 4759d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall 4769d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall // Helper function: create a CStyleCastExpr with trivial type source info. 4779d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, 4782de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall CastKind Kind, Expr *E) { 4799d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); 480f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo, 481f871d0cc377a1367b519a6cce26be74607566ebaJohn McCall SourceLocation(), SourceLocation()); 4829d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall } 48377cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner} 48477cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 4851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, 4861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump NamedDecl *D) { 487f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall if (const FunctionProtoType *fproto 488723df245307a530da5433dfb43accf187dc3e243Abramo Bagnara = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) { 4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), 49054055232a5ddb9529726e934301b125cb720a273Steve Naroff E = fproto->arg_type_end(); I && (I != E); ++I) 49101f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(*I)) { 49254055232a5ddb9529726e934301b125cb720a273Steve Naroff // All the args are checked/rewritten. Don't call twice! 49354055232a5ddb9529726e934301b125cb720a273Steve Naroff RewriteBlockPointerDecl(D); 49454055232a5ddb9529726e934301b125cb720a273Steve Naroff break; 49554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 49654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 49754055232a5ddb9529726e934301b125cb720a273Steve Naroff} 49854055232a5ddb9529726e934301b125cb720a273Steve Naroff 49954055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { 5006217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek const PointerType *PT = funcType->getAs<PointerType>(); 50154055232a5ddb9529726e934301b125cb720a273Steve Naroff if (PT && PointerTypeTakesAnyBlockArguments(funcType)) 50272564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); 50354055232a5ddb9529726e934301b125cb720a273Steve Naroff} 50454055232a5ddb9529726e934301b125cb720a273Steve Naroff 505b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanianstatic bool IsHeaderFile(const std::string &Filename) { 506b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian std::string::size_type DotPos = Filename.rfind('.'); 5071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 508b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian if (DotPos == std::string::npos) { 509b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // no file extension 5101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 511b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian } 5121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 513b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); 514b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // C header: .h 515b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // C++ header: .hh or .H; 516b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian return Ext == "h" || Ext == "hh" || Ext == "H"; 5171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 518b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian 5195f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerRewriteObjC::RewriteObjC(std::string inFile, raw_ostream* OS, 520c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman Diagnostic &D, const LangOptions &LOpts, 521c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool silenceMacroWarn) 522c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS), 523c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman SilenceRewriteMacroWarning(silenceMacroWarn) { 524a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff IsHeader = IsHeaderFile(inFile); 5251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, 526a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff "rewriting sub-expression within a macro (may not be correct)"); 5271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning, 5288189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek "rewriter doesn't support user-specified control flow semantics " 5298189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek "for @try/@finally (code may not execute properly)"); 530a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff} 531a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff 532bce831b1ecda51cd1abd3c07467294ffd21f5f86Eli FriedmanASTConsumer *clang::CreateObjCRewriter(const std::string& InFile, 5335f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner raw_ostream* OS, 5341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diagnostic &Diags, 535c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman const LangOptions &LOpts, 536c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool SilenceRewriteMacroWarning) { 537c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); 538e365c50a21cb02e0219433db0c4461566ad4a597Chris Lattner} 53977cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 540b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::Initialize(ASTContext &context) { 5419e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner Context = &context; 5429e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SM = &Context->getSourceManager(); 543ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis TUDecl = Context->getTranslationUnitDecl(); 5449e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendFunctionDecl = 0; 5459e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendSuperFunctionDecl = 0; 5469e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendStretFunctionDecl = 0; 5479e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendSuperStretFunctionDecl = 0; 5489e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendFpretFunctionDecl = 0; 5499e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner GetClassFunctionDecl = 0; 5509e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner GetMetaClassFunctionDecl = 0; 551d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian GetSuperClassFunctionDecl = 0; 5529e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SelGetUidFunctionDecl = 0; 5539e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner CFStringFunctionDecl = 0; 5549e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner ConstantStringClassReference = 0; 5559e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner NSStringRecord = 0; 55654055232a5ddb9529726e934301b125cb720a273Steve Naroff CurMethodDef = 0; 55754055232a5ddb9529726e934301b125cb720a273Steve Naroff CurFunctionDef = 0; 558abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 559b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff GlobalVarDecl = 0; 5609e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SuperStructDecl = 0; 561621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolTypeDecl = 0; 5629630ec5b6785e5b6e1c71aeddcad05005beb7483Steve Naroff ConstantStringDecl = 0; 5639e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner BcLabelCount = 0; 564c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff SuperContructorFunctionDecl = 0; 565d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff NumObjCStringLiterals = 0; 56668272b86b36f89d7ceba1ec9a2826c2126adc72eSteve Naroff PropParentMap = 0; 56768272b86b36f89d7ceba1ec9a2826c2126adc72eSteve Naroff CurrentBody = 0; 568b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff DisableReplaceStmt = false; 569f292fcf6bd5118499a830e0950429effeb373c28Fariborz Jahanian objc_impl_method = false; 5701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5719e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner // Get the ID and start/end of the main file. 5729e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileID = SM->getMainFileID(); 5739e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID); 5749e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileStart = MainBuf->getBufferStart(); 5759e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileEnd = MainBuf->getBufferEnd(); 5761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5772c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions()); 5781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5799e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner // declaring objc_selector outside the parameter list removes a silly 5809e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner // scope related warning... 581ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff if (IsHeader) 58262c2632c555bc701d41f0eb1803bbf0660d7f0c0Steve Naroff Preamble = "#pragma once\n"; 583ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "struct objc_selector; struct objc_class;\n"; 58446a98a7df016b4a6835a1902c2f8ff2a3a8012baSteve Naroff Preamble += "struct __rw_objc_super { struct objc_object *object; "; 585ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "struct objc_object *superClass; "; 586c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff if (LangOpts.Microsoft) { 587c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff // Add a constructor for creating temporary objects. 5888189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) " 5898189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ": "; 590ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "object(o), superClass(s) {} "; 591c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff } 592ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "};\n"; 593ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; 594ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "typedef struct objc_object Protocol;\n"; 595ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#define _REWRITER_typedef_Protocol\n"; 596ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#endif\n"; 5974ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff if (LangOpts.Microsoft) { 5984ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; 5994ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; 6004ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff } else 6017c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; 6024ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend"; 603ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 6044ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper"; 605ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 6064ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend_stret"; 607ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 6084ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper_stret"; 609ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 6104ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret"; 611ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 6124ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass"; 613ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(const char *);\n"; 614d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; 615d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian Preamble += "(struct objc_class *);\n"; 6164ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass"; 617ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(const char *);\n"; 6184ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n"; 6194ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n"; 6204ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n"; 6214ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n"; 6224ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match"; 623580ca7859330f8c92a66b09c21399ed9efa3991eSteve Naroff Preamble += "(struct objc_class *, struct objc_object *);\n"; 62459f05a48a7b0353090da2b8f878c2d760e55731cSteve Naroff // @synchronized hooks. 6254ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n"; 6264ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n"; 6274ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; 628ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; 629ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "struct __objcFastEnumerationState {\n\t"; 630ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "unsigned long state;\n\t"; 631b10f273eb60db2f2205b955fe4f7a43e09a5e2f2Steve Naroff Preamble += "void **itemsPtr;\n\t"; 632ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "unsigned long *mutationsPtr;\n\t"; 633ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "unsigned long extra[5];\n};\n"; 6344ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; 635ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#define __FASTENUMERATIONSTATE\n"; 636ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#endif\n"; 637ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; 638ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "struct __NSConstantStringImpl {\n"; 639ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " int *isa;\n"; 640ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " int flags;\n"; 641ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " char *str;\n"; 642ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " long length;\n"; 643ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "};\n"; 64488bee7451399c04b7e1c49cdeb16fadf0dd66f58Steve Naroff Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; 64588bee7451399c04b7e1c49cdeb16fadf0dd66f58Steve Naroff Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; 64688bee7451399c04b7e1c49cdeb16fadf0dd66f58Steve Naroff Preamble += "#else\n"; 6474ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; 64888bee7451399c04b7e1c49cdeb16fadf0dd66f58Steve Naroff Preamble += "#endif\n"; 649ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; 650ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#endif\n"; 65154055232a5ddb9529726e934301b125cb720a273Steve Naroff // Blocks preamble. 65254055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "#ifndef BLOCK_IMPL\n"; 65354055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "#define BLOCK_IMPL\n"; 65454055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "struct __block_impl {\n"; 65554055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += " void *isa;\n"; 65654055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += " int Flags;\n"; 65701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Preamble += " int Reserved;\n"; 65854055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += " void *FuncPtr;\n"; 65954055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "};\n"; 6605bc60d0c324a1b3984cd4a32acb587c8f873ab5fSteve Naroff Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; 661c9c1e9c4b513e83146eff1728142683980df26a7Steve Naroff Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; 6627c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Preamble += "extern \"C\" __declspec(dllexport) " 6637c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian "void _Block_object_assign(void *, const void *, const int);\n"; 664a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; 665a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; 666a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; 667a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "#else\n"; 668cd826370bb146a25bddea48399953dd3077710cfSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; 669cd826370bb146a25bddea48399953dd3077710cfSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; 670a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; 671a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; 672a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "#endif\n"; 67354055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "#endif\n"; 674a48396e10f75966ed5ca974dcc73907ce8c80deeSteve Naroff if (LangOpts.Microsoft) { 6754ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; 6764ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; 677553e583e1d30fe30ac2de3526536bbebee6da1ceChris Lattner Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. 678a48396e10f75966ed5ca974dcc73907ce8c80deeSteve Naroff Preamble += "#define __attribute__(X)\n"; 679553e583e1d30fe30ac2de3526536bbebee6da1ceChris Lattner Preamble += "#endif\n"; 68034204195de802e9d3cc8d54355b2ad4b3c27f188Fariborz Jahanian Preamble += "#define __weak\n"; 681a48396e10f75966ed5ca974dcc73907ce8c80deeSteve Naroff } 6822086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian else { 68352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian Preamble += "#define __block\n"; 6842086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian Preamble += "#define __weak\n"; 6852086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian } 686df496529b7009d6e58f335926884200b38d27687Fariborz Jahanian // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long 687df496529b7009d6e58f335926884200b38d27687Fariborz Jahanian // as this avoids warning in any 64bit/32bit compilation model. 688df496529b7009d6e58f335926884200b38d27687Fariborz Jahanian Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; 6899e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner} 6909e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner 6919e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner 692f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 693f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner// Top Level Driver Code 694f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 695f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 696682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattnervoid RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { 697e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek if (Diags.hasErrorOccurred()) 698e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek return; 699e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek 7002c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // Two cases: either the decl could be in the main file, or it could be in a 7012c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // #included file. If the former, rewrite it now. If the later, check to see 7022c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // if we rewrote the #include/#import. 7032c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner SourceLocation Loc = D->getLocation(); 704402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth Loc = SM->getExpansionLoc(Loc); 7051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7062c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // If this is for a builtin, ignore it. 7072c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner if (Loc.isInvalid()) return; 7082c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner 709ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Look for built-in declarations that we need to refer during the rewrite. 710ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 71109b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff RewriteFunctionDecl(FD); 712248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) { 713beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff // declared in <Foundation/NSString.h> 7144087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar if (FVD->getName() == "_NSConstantStringClassReference") { 715beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff ConstantStringClassReference = FVD; 716beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff return; 717beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff } 718a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) { 719bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff RewriteInterfaceDecl(MD); 720a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { 721423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff RewriteCategoryDecl(CD); 722a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { 723752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff RewriteProtocolDecl(PD); 7241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else if (ObjCForwardProtocolDecl *FP = 725a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek dyn_cast<ObjCForwardProtocolDecl>(D)){ 726d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian RewriteForwardProtocolDecl(FP); 727d04341000d35c8808a72838b057eed7bf13b7661Douglas Gregor } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { 728d04341000d35c8808a72838b057eed7bf13b7661Douglas Gregor // Recurse into linkage specifications 72917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis for (DeclContext::decl_iterator DI = LSD->decls_begin(), 73017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis DIEnd = LSD->decls_end(); 731a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian DI != DIEnd; ) { 732a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian if (isa<ObjCClassDecl>((*DI))) { 733a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian SmallVector<Decl *, 8> DG; 734a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian Decl *D = (*DI); 735a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian SourceLocation Loc = D->getLocation(); 736a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian while (DI != DIEnd && 737a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian isa<ObjCClassDecl>(D) && D->getLocation() == Loc) { 738a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian DG.push_back(D); 739a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian ++DI; 740a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian D = (*DI); 741a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 742a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian RewriteForwardClassDecl(DG); 743a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian continue; 744a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 745682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner HandleTopLevelSingleDecl(*DI); 746a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian ++DI; 747a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 748ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff } 749f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // If we have a decl in the main file, see if we should rewrite it. 750cf7e958483735935de6e0a64aa1e55a967116303Ted Kremenek if (SM->isFromMainFile(Loc)) 7512c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner return HandleDeclInMainFile(D); 7522c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner} 7532c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner 754f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 755f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner// Syntactic (non-AST) Rewriting Code 756f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 757f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 758b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteInclude() { 7592b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); 7605f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef MainBuf = SM->getBufferData(MainFileID); 761f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer const char *MainBufStart = MainBuf.begin(); 762f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer const char *MainBufEnd = MainBuf.end(); 763452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian size_t ImportLen = strlen("import"); 7641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 765af57b46f12e9dd48485fa27f2088f85466ee9292Fariborz Jahanian // Loop over the whole file, looking for includes. 766452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { 767452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (*BufPtr == '#') { 768452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (++BufPtr == MainBufEnd) 769452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian return; 770452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian while (*BufPtr == ' ' || *BufPtr == '\t') 771452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (++BufPtr == MainBufEnd) 772452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian return; 773452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (!strncmp(BufPtr, "import", ImportLen)) { 774452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian // replace import with include 7751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation ImportLoc = 776452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian LocStart.getFileLocWithOffset(BufPtr-MainBufStart); 777d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(ImportLoc, ImportLen, "include"); 778452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian BufPtr += ImportLen; 779452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 780452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 781452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 7828a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner} 7838a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 7842d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanianstatic std::string getIvarAccessString(ObjCIvarDecl *OID) { 7852d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface(); 786eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff std::string S; 787eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S = "((struct "; 788eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S += ClassDecl->getIdentifier()->getName(); 789eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S += "_IMPL *)self)->"; 7905ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar S += OID->getName(); 791eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return S; 792eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff} 793eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff 794a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroffvoid RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 795a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCImplementationDecl *IMD, 796a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCCategoryImplDecl *CID) { 7977c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian static bool objcGetPropertyDefined = false; 7987c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian static bool objcSetPropertyDefined = false; 799d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff SourceLocation startLoc = PID->getLocStart(); 800d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, "// "); 801eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 802eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff assert((*startBuf == '@') && "bogus @synthesize location"); 803eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 804eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff assert((*semiBuf == ';') && "@synthesize: can't find ';'"); 8058189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek SourceLocation onePastSemiLoc = 8068189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek startLoc.getFileLocWithOffset(semiBuf-startBuf+1); 807eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff 808eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 809eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return; // FIXME: is this correct? 8101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 811eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff // Generate the 'getter' function. 812eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff ObjCPropertyDecl *PD = PID->getPropertyDecl(); 813eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); 8141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 815dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff if (!OID) 816dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff return; 8177c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian unsigned Attributes = PD->getPropertyAttributes(); 818ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (!PD->getGetterMethodDecl()->isDefined()) { 819ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) && 820ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian (Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 821ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_copy)); 822ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian std::string Getr; 823ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (GenGetProperty && !objcGetPropertyDefined) { 824ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian objcGetPropertyDefined = true; 825ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // FIXME. Is this attribute correct in all cases? 826ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr = "\nextern \"C\" __declspec(dllimport) " 827ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian "id objc_getProperty(id, SEL, long, bool);\n"; 828ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } 829ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian RewriteObjCMethodDecl(OID->getContainingInterface(), 830ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian PD->getGetterMethodDecl(), Getr); 831ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "{ "; 832ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // Synthesize an explicit cast to gain access to the ivar. 833ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // See objc-act.c:objc_synthesize_new_getter() for details. 834ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (GenGetProperty) { 835ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) 836ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "typedef "; 837ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian const FunctionType *FPRetType = 0; 838ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr, 839ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian FPRetType); 840ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += " _TYPE"; 841ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (FPRetType) { 842ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ")"; // close the precedence "scope" for "*". 8437c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 844ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // Now, emit the argument types (if any). 845ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){ 846ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "("; 847ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 848ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (i) Getr += ", "; 849ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian std::string ParamStr = FT->getArgType(i).getAsString( 850ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Context->PrintingPolicy); 851ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ParamStr; 852ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } 853ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (FT->isVariadic()) { 854ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (FT->getNumArgs()) Getr += ", "; 855ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "..."; 856ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } 857ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ")"; 858ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } else 859ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "()"; 860ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } 861ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ";\n"; 862ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "return (_TYPE)"; 863ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "objc_getProperty(self, _cmd, "; 864ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian SynthesizeIvarOffsetComputation(OID, Getr); 865ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ", 1)"; 8667c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 867ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian else 868ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "return " + getIvarAccessString(OID); 869ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "; }"; 870ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian InsertText(onePastSemiLoc, Getr); 8717c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 872ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian 873ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined()) 874eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return; 8751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 876eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff // Generate the 'setter' function. 877eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff std::string Setr; 8787c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 8797c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_copy); 8807c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (GenSetProperty && !objcSetPropertyDefined) { 8817c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian objcSetPropertyDefined = true; 8827c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian // FIXME. Is this attribute correct in all cases? 8837c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr = "\nextern \"C\" __declspec(dllimport) " 8847c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian "void objc_setProperty (id, SEL, long, id, bool, bool);\n"; 8857c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8867c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 8872d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian RewriteObjCMethodDecl(OID->getContainingInterface(), 8882d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian PD->getSetterMethodDecl(), Setr); 889eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff Setr += "{ "; 890dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff // Synthesize an explicit cast to initialize the ivar. 89115f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff // See objc-act.c:objc_synthesize_new_setter() for details. 8927c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (GenSetProperty) { 8937c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "objc_setProperty (self, _cmd, "; 8942d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian SynthesizeIvarOffsetComputation(OID, Setr); 8957c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += ", (id)"; 8964087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar Setr += PD->getName(); 8977c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += ", "; 8987c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) 8997c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "0, "; 9007c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else 9017c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "1, "; 9027c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (Attributes & ObjCPropertyDecl::OBJC_PR_copy) 9037c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "1)"; 9047c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else 9057c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "0)"; 9067c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 9077c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else { 9082d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian Setr += getIvarAccessString(OID) + " = "; 9094087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar Setr += PD->getName(); 9107c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 911dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff Setr += "; }"; 912d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, Setr); 913d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff} 9148a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 915a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanianstatic void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, 916a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian std::string &typedefString) { 917a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "#ifndef _REWRITER_typedef_"; 918a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 919a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "\n"; 920a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "#define _REWRITER_typedef_"; 921a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 922a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "\n"; 923a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "typedef struct objc_object "; 924a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 925a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ";\n#endif\n"; 926a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian} 927a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian 928a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanianvoid RewriteObjC::RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, 929a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const std::string &typedefString) { 930a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian SourceLocation startLoc = ClassDecl->getLocation(); 931a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 932a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const char *semiPtr = strchr(startBuf, ';'); 933a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian // Replace the @class with typedefs corresponding to the classes. 934a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); 935a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian} 936a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian 93795ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanianvoid RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) { 938f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner std::string typedefString; 93995ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 94095ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian ObjCClassDecl *ClassDecl = cast<ObjCClassDecl>(*I); 94195ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl(); 94295ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian if (I == D.begin()) { 943a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian // Translate to typedef's that forward reference structs with the same name 944a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian // as the class. As a convenience, we include the original declaration 945a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian // as a comment. 94695ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian typedefString += "// @class "; 94795ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 94891fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian typedefString += ";\n"; 94995ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian } 950a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian RewriteOneForwardClassDecl(ForwardDecl, typedefString); 951934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff } 952a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian DeclGroupRef::iterator I = D.begin(); 953a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian RewriteForwardClassEpilogue(cast<ObjCClassDecl>(*I), typedefString); 954a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian} 9551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 956a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanianvoid RewriteObjC::RewriteForwardClassDecl( 957a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const llvm::SmallVector<Decl*, 8> &D) { 958a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian std::string typedefString; 959a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian for (unsigned i = 0; i < D.size(); i++) { 960a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian ObjCClassDecl *ClassDecl = cast<ObjCClassDecl>(D[i]); 961a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl(); 962a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian if (i == 0) { 963a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "// @class "; 964a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 965a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ";\n"; 966a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 967a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian RewriteOneForwardClassDecl(ForwardDecl, typedefString); 968a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 969a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian RewriteForwardClassEpilogue(cast<ObjCClassDecl>(D[0]), typedefString); 970f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner} 971f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 972b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { 973d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian // When method is a synthesized one, such as a getter/setter there is 974d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian // nothing to rewrite. 97588914801a4d73e321c6f74f97df7d7b11c298bc6Fariborz Jahanian if (Method->isImplicit()) 976d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian return; 97758dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff SourceLocation LocStart = Method->getLocStart(); 97858dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff SourceLocation LocEnd = Method->getLocEnd(); 9791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 980642116259e8df6286063a17361c20e95b5017a0aChandler Carruth if (SM->getExpansionLineNumber(LocEnd) > 981642116259e8df6286063a17361c20e95b5017a0aChandler Carruth SM->getExpansionLineNumber(LocStart)) { 982d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LocStart, "#if 0\n"); 983d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocEnd, 1, ";\n#endif\n"); 98458dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff } else { 985d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LocStart, "// "); 986423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff } 987423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff} 988423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff 9891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) { 990d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian SourceLocation Loc = prop->getAtLoc(); 9911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 992d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(Loc, 0, "// "); 9936327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff // FIXME: handle properties that are declared across multiple lines. 994957cf65bf32fe7c84886a2296d0b4ede40029850Fariborz Jahanian} 995957cf65bf32fe7c84886a2296d0b4ede40029850Fariborz Jahanian 996b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { 997423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff SourceLocation LocStart = CatDecl->getLocStart(); 9981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 999423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff // FIXME: handle category headers that are declared across multiple lines. 1000d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 10011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 100213751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), 100313751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian E = CatDecl->prop_end(); I != E; ++I) 100413751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian RewriteProperty(*I); 100513751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian 10061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCCategoryDecl::instmeth_iterator 10071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); 10086ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 100958dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 10101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCCategoryDecl::classmeth_iterator 101117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); 10126ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 101358dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 101458dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 1015423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff // Lastly, comment out the @end. 101673d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(CatDecl->getAtEndRange().getBegin(), 101773d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian strlen("@end"), "/* @end */"); 1018423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff} 1019423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff 1020b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { 1021752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff SourceLocation LocStart = PDecl->getLocStart(); 10221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1023752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff // FIXME: handle protocol headers that are declared across multiple lines. 1024d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 10251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCProtocolDecl::instmeth_iterator 10271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 10286ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 102958dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 10306ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor for (ObjCProtocolDecl::classmeth_iterator 103117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 10326ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 103358dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 103458dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 103507acdf4c776fd98e315bc1de380af8ba3c25559eFariborz Jahanian for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(), 103607acdf4c776fd98e315bc1de380af8ba3c25559eFariborz Jahanian E = PDecl->prop_end(); I != E; ++I) 103707acdf4c776fd98e315bc1de380af8ba3c25559eFariborz Jahanian RewriteProperty(*I); 103807acdf4c776fd98e315bc1de380af8ba3c25559eFariborz Jahanian 1039752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff // Lastly, comment out the @end. 1040782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); 104173d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(LocEnd, strlen("@end"), "/* @end */"); 10428cc764c67afc249628ba4f65b8e2d2ad461112ffSteve Naroff 1043b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian // Must comment out @optional/@required 1044b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 1045b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1046b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian for (const char *p = startBuf; p < endBuf; p++) { 1047b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { 10488cc764c67afc249628ba4f65b8e2d2ad461112ffSteve Naroff SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); 1049d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); 10501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1051b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1052b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { 10538cc764c67afc249628ba4f65b8e2d2ad461112ffSteve Naroff SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); 1054d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); 10551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1056b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1057b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1058752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff} 1059752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff 1060b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) { 1061d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian SourceLocation LocStart = PDecl->getLocation(); 1062b7fa992be16668b61f722e6e125137216860469eSteve Naroff if (LocStart.isInvalid()) 1063b7fa992be16668b61f722e6e125137216860469eSteve Naroff assert(false && "Invalid SourceLocation"); 1064d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian // FIXME: handle forward protocol that are declared across multiple lines. 1065d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 1066d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian} 1067d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian 10687c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanianvoid RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr, 10697c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *&FPRetType) { 10707c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (T->isObjCQualifiedIdType()) 1071c569249ca0ab755ac79d8cbbfcb2bcae19743624Fariborz Jahanian ResultStr += "id"; 10727c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else if (T->isFunctionPointerType() || 10737c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian T->isBlockPointerType()) { 107476e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // needs special handling, since pointer-to-functions have special 107576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // syntax (where a decaration models use). 10767c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian QualType retType = T; 1077f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff QualType PointeeTy; 10786217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (const PointerType* PT = retType->getAs<PointerType>()) 1079f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff PointeeTy = PT->getPointeeType(); 10806217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) 1081f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff PointeeTy = BPT->getPointeeType(); 1082183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall if ((FPRetType = PointeeTy->getAs<FunctionType>())) { 1083fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += FPRetType->getResultType().getAsString( 1084fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar Context->PrintingPolicy); 1085f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff ResultStr += "(*"; 108676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 108776e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } else 1088fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += T.getAsString(Context->PrintingPolicy); 10897c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian} 10907c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 10912d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanianvoid RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 10922d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian ObjCMethodDecl *OMD, 10937c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian std::string &ResultStr) { 10947c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian //fprintf(stderr,"In RewriteObjCMethodDecl\n"); 10957c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *FPRetType = 0; 10967c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian ResultStr += "\nstatic "; 10977c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType); 1098531a1ea2f4c88817f3dc0f4628dfc34536f54c5eFariborz Jahanian ResultStr += " "; 10991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 110048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Unique method name 1101b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian std::string NameStr; 11021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1103f8d49f64ef6ab7e632717a31631fc289aab69428Douglas Gregor if (OMD->isInstanceMethod()) 1104b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_I_"; 110548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian else 1106b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_C_"; 11071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11082d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian NameStr += IDecl->getNameAsString(); 1109b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_"; 11101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (ObjCCategoryImplDecl *CID = 11123e0a540b6d846178857289ec0eb8470a278d11a3Steve Naroff dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 1113d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner NameStr += CID->getNameAsString(); 1114b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_"; 111548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 11161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Append selector names, replacing ':' with '_' 1117077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner { 1118077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner std::string selString = OMD->getSelector().getAsString(); 111948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian int len = selString.size(); 112048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian for (int i = 0; i < len; i++) 112148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian if (selString[i] == ':') 112248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian selString[i] = '_'; 1123b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += selString; 112448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 1125b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian // Remember this name for metadata emission 1126b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian MethodInternalNames[OMD] = NameStr; 1127b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian ResultStr += NameStr; 11281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Rewrite arguments 113048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += "("; 11311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 113248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // invisible arguments 1133f8d49f64ef6ab7e632717a31631fc289aab69428Douglas Gregor if (OMD->isInstanceMethod()) { 11342d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian QualType selfTy = Context->getObjCInterfaceType(IDecl); 113548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian selfTy = Context->getPointerType(selfTy); 113605b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff if (!LangOpts.Microsoft) { 11372d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl))) 113805b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff ResultStr += "struct "; 113905b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff } 114005b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff // When rewriting for Microsoft, explicitly omit the structure name. 11412d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian ResultStr += IDecl->getNameAsString(); 114261ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff ResultStr += " *"; 114348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 114448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian else 1145fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += Context->getObjCClassType().getAsString( 1146fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar Context->PrintingPolicy); 11471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 114848a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += " self, "; 1149fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += Context->getObjCSelType().getAsString(Context->PrintingPolicy); 115048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += " _cmd"; 11511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Method arguments. 115389951a86b594513c2a013532ed45d197413b1087Chris Lattner for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 115489951a86b594513c2a013532ed45d197413b1087Chris Lattner E = OMD->param_end(); PI != E; ++PI) { 115589951a86b594513c2a013532ed45d197413b1087Chris Lattner ParmVarDecl *PDecl = *PI; 115648a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += ", "; 1157543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff if (PDecl->getType()->isObjCQualifiedIdType()) { 1158543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff ResultStr += "id "; 1159d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += PDecl->getNameAsString(); 1160543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff } else { 1161d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = PDecl->getNameAsString(); 11624fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian QualType QT = PDecl->getType(); 11634fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian // Make sure we convert "t (^)(...)" to "t (*)(...)". 11644fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (convertBlockPointerToFunctionPointer(QT)) 11654fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian QT.getAsStringInternal(Name, Context->PrintingPolicy); 11664fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian else 1167d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PDecl->getType().getAsStringInternal(Name, Context->PrintingPolicy); 1168543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff ResultStr += Name; 1169543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff } 117048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 11717c39ff7eb3dd7ae9b2b81cb66a139c9b52f47f1dFariborz Jahanian if (OMD->isVariadic()) 11727c39ff7eb3dd7ae9b2b81cb66a139c9b52f47f1dFariborz Jahanian ResultStr += ", ..."; 1173531a1ea2f4c88817f3dc0f4628dfc34536f54c5eFariborz Jahanian ResultStr += ") "; 11741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 117576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FPRetType) { 117676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ")"; // close the precedence "scope" for "*". 11771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 117876e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // Now, emit the argument types (if any). 117972564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { 118076e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "("; 118176e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 118276e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (i) ResultStr += ", "; 1183fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string ParamStr = FT->getArgType(i).getAsString( 1184fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar Context->PrintingPolicy); 118576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ParamStr; 118676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 118776e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FT->isVariadic()) { 118876e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FT->getNumArgs()) ResultStr += ", "; 118976e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "..."; 119076e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 119176e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ")"; 119276e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } else { 119376e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "()"; 119476e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 119576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 119648a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian} 11974afa39deaa245592977136d367251ee2c173dd8dDouglas Gregorvoid RewriteObjC::RewriteImplementationDecl(Decl *OID) { 1198a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); 1199a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); 12001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1201a135216595c00ddb5ce5f5b853a3d1f4037a13b7Fariborz Jahanian InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// "); 12021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1203a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek for (ObjCCategoryImplDecl::instmeth_iterator 120417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), 120517945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); 1206653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 120748a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian std::string ResultStr; 1208a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *OMD = *I; 12092d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 121048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian SourceLocation LocStart = OMD->getLocStart(); 12116fb0aee4f9dc261bbec72e1283ad8dc0557a6d96Argyrios Kyrtzidis SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 1212d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 121348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 121448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1215d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, ResultStr); 121648a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 12171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1218a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek for (ObjCCategoryImplDecl::classmeth_iterator 121917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), 122017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); 1221653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 122248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian std::string ResultStr; 1223a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *OMD = *I; 12242d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 122548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian SourceLocation LocStart = OMD->getLocStart(); 12266fb0aee4f9dc261bbec72e1283ad8dc0557a6d96Argyrios Kyrtzidis SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 12271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 122848a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 122948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1230d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, ResultStr); 123148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 1232d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff for (ObjCCategoryImplDecl::propimpl_iterator 123317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), 12341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); 1235653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 1236a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff RewritePropertyImplDecl(*I, IMD, CID); 1237d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff } 1238d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff 1239d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// "); 124048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian} 124148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian 1242b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 1243f908a87299d278164540f90b5b6e6cab7b14fb41Steve Naroff std::string ResultStr; 1244a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (!ObjCForwardDecls.count(ClassDecl)) { 12456c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff // we haven't seen a forward decl - generate a typedef. 12465086a8df9a269acc2e4f0deb1895d4a9e9d13f4dSteve Naroff ResultStr = "#ifndef _REWRITER_typedef_"; 1247d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 124832174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "\n"; 124932174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "#define _REWRITER_typedef_"; 1250d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 125132174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "\n"; 125261ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff ResultStr += "typedef struct objc_object "; 1253d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 125432174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += ";\n#endif\n"; 12556c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff // Mark this typedef as having been generated. 1256a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCForwardDecls.insert(ClassDecl); 12576c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff } 1258a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek SynthesizeObjCInternalStruct(ClassDecl, ResultStr); 12591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), 126117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = ClassDecl->prop_end(); I != E; ++I) 12626327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff RewriteProperty(*I); 12631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::instmeth_iterator 126417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); 12656ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 126658dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 12671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::classmeth_iterator 12681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); 12696ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 127058dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 127158dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 12722feac5e559ca5c9693a3a19905ab106b9c52e193Steve Naroff // Lastly, comment out the @end. 127373d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), 127473d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian "/* @end */"); 1275bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff} 1276bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff 1277f2ad2c92720f0e25c032188783a1d6374155f03aFariborz JahanianStmt *RewriteObjC::RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt, 1278b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff SourceRange SrcRange) { 1279f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian ObjCMethodDecl *OMD = 0; 1280f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian QualType Ty; 1281f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Selector Sel; 128254bd4577762228fdca4367dbc3af5e13e7f21389Duncan Sands Stmt *Receiver = 0; 12838ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian bool Super = false; 12848ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian QualType SuperTy; 12858ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian SourceLocation SuperLocation; 1286f40f0d5a382395e0301d7dcbeaa2b8e90b8973b1Argyrios Kyrtzidis SourceLocation SelectorLoc; 1287f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ObjCImplicitSetterGetterRefExpr. 1288c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // This allows us to reuse all the fun and games in SynthMessageExpr(). 128912f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall if (ObjCPropertyRefExpr *PropRefExpr = 129012f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) { 1291f40f0d5a382395e0301d7dcbeaa2b8e90b8973b1Argyrios Kyrtzidis SelectorLoc = PropRefExpr->getLocation(); 129212f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall if (PropRefExpr->isExplicitProperty()) { 129312f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty(); 129412f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall OMD = PDecl->getSetterMethodDecl(); 129512f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall Ty = PDecl->getType(); 129612f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall Sel = PDecl->getSetterName(); 129712f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall } else { 129812f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall OMD = PropRefExpr->getImplicitPropertySetter(); 129912f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall Sel = OMD->getSelector(); 130012f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall Ty = PropRefExpr->getType(); 130112f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall } 13028ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian Super = PropRefExpr->isSuperReceiver(); 130312f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall if (!Super) { 13048ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian Receiver = PropRefExpr->getBase(); 130512f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall } else { 130612f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall SuperTy = PropRefExpr->getSuperReceiverType(); 130712f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall SuperLocation = PropRefExpr->getReceiverLocation(); 13088ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian } 1309f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian } 1310f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian 1311f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian assert(OMD && "RewritePropertyOrImplicitSetter - null OMD"); 13125f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr *, 1> ExprVec; 1313c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff ExprVec.push_back(newStmt); 13141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1315f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian ObjCMessageExpr *MsgExpr; 13168ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian if (Super) 131704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExpr = ObjCMessageExpr::Create(*Context, 1318f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Ty.getNonReferenceType(), 1319f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Expr::getValueKindForType(Ty), 132004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME?*/SourceLocation(), 13218ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian SuperLocation, 132204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*IsInstanceSuper=*/true, 13238ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian SuperTy, 1324f40f0d5a382395e0301d7dcbeaa2b8e90b8973b1Argyrios Kyrtzidis Sel, SelectorLoc, OMD, 132504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ExprVec[0], 1, 132604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME:*/SourceLocation()); 1327e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian else { 1328e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian // FIXME. Refactor this into common code with that in 1329e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian // RewritePropertyOrImplicitGetter 1330e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian assert(Receiver && "RewritePropertyOrImplicitSetter - null Receiver"); 1331e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian if (Expr *Exp = dyn_cast<Expr>(Receiver)) 1332e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian if (PropGetters[Exp]) 1333e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian // This allows us to handle chain/nested property/implicit getters. 1334e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian Receiver = PropGetters[Exp]; 1335e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian 133604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExpr = ObjCMessageExpr::Create(*Context, 1337f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Ty.getNonReferenceType(), 1338f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Expr::getValueKindForType(Ty), 133904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME: */SourceLocation(), 134004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor cast<Expr>(Receiver), 1341f40f0d5a382395e0301d7dcbeaa2b8e90b8973b1Argyrios Kyrtzidis Sel, SelectorLoc, OMD, 134204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ExprVec[0], 1, 134304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME:*/SourceLocation()); 1344e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian } 1345c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); 13461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1347c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // Now do the actual rewrite. 1348b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange); 1349e58ee0ca7cfad6ee75a088e7a6a090526e18da50Steve Naroff //delete BinOp; 13508189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references 13518189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // to things that stay around. 13528189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Context->Deallocate(MsgExpr); 1353c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff return ReplacingStmt; 135415f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff} 135515f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 1356f2ad2c92720f0e25c032188783a1d6374155f03aFariborz JahanianStmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) { 1357f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ImplicitGetter. 135815f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff // This allows us to reuse all the fun and games in SynthMessageExpr(). 13593b562af1b3675d22e8ad0cef6f48343b3c2ee02dTed Kremenek Stmt *Receiver = 0; 1360f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian ObjCMethodDecl *OMD = 0; 1361f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian QualType Ty; 1362f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Selector Sel; 13638ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian bool Super = false; 13648ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian QualType SuperTy; 13658ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian SourceLocation SuperLocation; 1366f40f0d5a382395e0301d7dcbeaa2b8e90b8973b1Argyrios Kyrtzidis SourceLocation SelectorLoc; 1367f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian if (ObjCPropertyRefExpr *PropRefExpr = 1368f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian dyn_cast<ObjCPropertyRefExpr>(PropOrGetterRefExpr)) { 1369f40f0d5a382395e0301d7dcbeaa2b8e90b8973b1Argyrios Kyrtzidis SelectorLoc = PropRefExpr->getLocation(); 137012f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall if (PropRefExpr->isExplicitProperty()) { 137112f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty(); 137212f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall OMD = PDecl->getGetterMethodDecl(); 137312f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall Ty = PDecl->getType(); 137412f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall Sel = PDecl->getGetterName(); 137512f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall } else { 137612f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall OMD = PropRefExpr->getImplicitPropertyGetter(); 137712f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall Sel = OMD->getSelector(); 137812f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall Ty = PropRefExpr->getType(); 137912f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall } 13808ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian Super = PropRefExpr->isSuperReceiver(); 13818ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian if (!Super) 13828ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian Receiver = PropRefExpr->getBase(); 13838ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian else { 138412f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall SuperTy = PropRefExpr->getSuperReceiverType(); 138512f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall SuperLocation = PropRefExpr->getReceiverLocation(); 13868ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian } 13878599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 1388f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian 1389f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian assert (OMD && "RewritePropertyOrImplicitGetter - OMD is null"); 1390f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian 1391f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian ObjCMessageExpr *MsgExpr; 13928ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian if (Super) 139304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExpr = ObjCMessageExpr::Create(*Context, 1394f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Ty.getNonReferenceType(), 1395f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Expr::getValueKindForType(Ty), 1396baac58d1a67aa76199418f82eab69ea36bd99acfFariborz Jahanian PropOrGetterRefExpr->getLocStart(), 13978ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian SuperLocation, 139804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*IsInstanceSuper=*/true, 13998ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian SuperTy, 1400f40f0d5a382395e0301d7dcbeaa2b8e90b8973b1Argyrios Kyrtzidis Sel, SelectorLoc, OMD, 140104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 0, 0, 1402baac58d1a67aa76199418f82eab69ea36bd99acfFariborz Jahanian PropOrGetterRefExpr->getLocEnd()); 1403e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian else { 1404e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian assert (Receiver && "RewritePropertyOrImplicitGetter - Receiver is null"); 1405e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian if (Expr *Exp = dyn_cast<Expr>(Receiver)) 1406e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian if (PropGetters[Exp]) 1407e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian // This allows us to handle chain/nested property/implicit getters. 1408e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian Receiver = PropGetters[Exp]; 140904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExpr = ObjCMessageExpr::Create(*Context, 1410f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Ty.getNonReferenceType(), 1411f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Expr::getValueKindForType(Ty), 1412baac58d1a67aa76199418f82eab69ea36bd99acfFariborz Jahanian PropOrGetterRefExpr->getLocStart(), 141304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor cast<Expr>(Receiver), 1414f40f0d5a382395e0301d7dcbeaa2b8e90b8973b1Argyrios Kyrtzidis Sel, SelectorLoc, OMD, 141504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 0, 0, 1416baac58d1a67aa76199418f82eab69ea36bd99acfFariborz Jahanian PropOrGetterRefExpr->getLocEnd()); 1417e0f83863595f5725791d88a799d20dbae38bed4aFariborz Jahanian } 141815f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 1419baac58d1a67aa76199418f82eab69ea36bd99acfFariborz Jahanian Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr, MsgExpr->getLocStart(), 1420baac58d1a67aa76199418f82eab69ea36bd99acfFariborz Jahanian MsgExpr->getLocEnd()); 14218599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff 14228599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (!PropParentMap) 14238599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropParentMap = new ParentMap(CurrentBody); 14243cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian bool NestedPropertyRef = false; 1425f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Stmt *Parent = PropParentMap->getParent(PropOrGetterRefExpr); 14263cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian ImplicitCastExpr*ICE=0; 14273cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian if (Parent) 14283cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian if ((ICE = dyn_cast<ImplicitCastExpr>(Parent))) { 14293cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian assert((ICE->getCastKind() == CK_GetObjCProperty) 14303cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian && "RewritePropertyOrImplicitGetter"); 14313cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian Parent = PropParentMap->getParent(Parent); 14323cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian NestedPropertyRef = (Parent && isa<ObjCPropertyRefExpr>(Parent)); 14333cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian } 14343cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian if (NestedPropertyRef) { 14358599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // We stash away the ReplacingStmt since actually doing the 14368599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // replacement/rewrite won't work for nested getters (e.g. obj.p.i) 14373cd1ea32c312dee47432dbb982f83bccff7356acFariborz Jahanian PropGetters[ICE] = ReplacingStmt; 14388189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references 14398189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // to things that stay around. 14408189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Context->Deallocate(MsgExpr); 1441f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian return PropOrGetterRefExpr; // return the original... 14428599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } else { 1443f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian ReplaceStmt(PropOrGetterRefExpr, ReplacingStmt); 14441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // delete PropRefExpr; elsewhere... 14458189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references 14468189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // to things that stay around. 14478189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Context->Deallocate(MsgExpr); 14488599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff return ReplacingStmt; 14498599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 145015f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff} 145115f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 14521eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpStmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, 14532b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian SourceLocation OrigStart, 14542b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian bool &replaced) { 1455a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCIvarDecl *D = IV->getDecl(); 145684ed600154d48d75f204795410aae808d7e4b7bdFariborz Jahanian const Expr *BaseExpr = IV->getBase(); 145754055232a5ddb9529726e934301b125cb720a273Steve Naroff if (CurMethodDef) { 14588f0954309eb885891908ecdfbb06d720c63128edFariborz Jahanian if (BaseExpr->getType()->isObjCObjectPointerType()) { 1459f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall const ObjCInterfaceType *iFaceDecl = 146084ed600154d48d75f204795410aae808d7e4b7bdFariborz Jahanian dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 1461ffbdead156eb0bc94d1cc7e28eadcca52dfb8194Fariborz Jahanian assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); 1462f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff // lookup which class implements the instance variable. 1463f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff ObjCInterfaceDecl *clsDeclared = 0; 14641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 14656ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor clsDeclared); 1466f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 14671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1468f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff // Synthesize an explicit cast to gain access to the ivar. 1469f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff std::string RecName = clsDeclared->getIdentifier()->getName(); 1470f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff RecName += "_IMPL"; 1471d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer IdentifierInfo *II = &Context->Idents.get(RecName); 1472465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 1473ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 1474ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara II); 1475f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 1476f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 14779d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 1478a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 14799d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall IV->getBase()); 1480f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff // Don't forget the parens to enforce the proper binding. 14818189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), 1482f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall IV->getBase()->getLocEnd(), 1483f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall castExpr); 14842b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian replaced = true; 14851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (IV->isFreeIvar() && 148654055232a5ddb9529726e934301b125cb720a273Steve Naroff CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) { 14878189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek MemberExpr *ME = new (Context) MemberExpr(PE, true, D, 1488f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall IV->getLocation(), 1489f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall D->getType(), 1490f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_LValue, OK_Ordinary); 1491f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete IV; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 1492f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff return ME; 1493c2a689b0bd0cda7bc1522dc0057f01f0897e6d3dSteve Naroff } 14947e20ffe322866f6a2e820e054da9bd0f6e9b0af4Fariborz Jahanian // Get the new text 14953b2c58ce3b1eadc5901efff30cf8bf1885936fe7Chris Lattner // Cannot delete IV->getBase(), since PE points to it. 14963b2c58ce3b1eadc5901efff30cf8bf1885936fe7Chris Lattner // Replace the old base with the cast. This is important when doing 14973b2c58ce3b1eadc5901efff30cf8bf1885936fe7Chris Lattner // embedded rewrites. For example, [newInv->_container addObject:0]. 14981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump IV->setBase(PE); 14993b2c58ce3b1eadc5901efff30cf8bf1885936fe7Chris Lattner return IV; 1500c2a689b0bd0cda7bc1522dc0057f01f0897e6d3dSteve Naroff } 150184472a897a99db80d49eb5ac1ac85d54b1cc6554Steve Naroff } else { // we are outside a method. 15029f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); 15031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15049f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Explicit ivar refs need to have a cast inserted. 15059f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // FIXME: consider sharing some of this code with the code above. 150626337b2f6d4b8dc7458a6e24dca05cb021a21861Fariborz Jahanian if (BaseExpr->getType()->isObjCObjectPointerType()) { 1507f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall const ObjCInterfaceType *iFaceDecl = 1508c374cd978abdeb289d360426129886f6e354a459Fariborz Jahanian dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 15099f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // lookup which class implements the instance variable. 15109f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff ObjCInterfaceDecl *clsDeclared = 0; 15111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 15126ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor clsDeclared); 15139f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 15141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15159f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Synthesize an explicit cast to gain access to the ivar. 15169f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff std::string RecName = clsDeclared->getIdentifier()->getName(); 15179f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff RecName += "_IMPL"; 1518d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer IdentifierInfo *II = &Context->Idents.get(RecName); 1519465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 1520ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 1521ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara II); 15229f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 15239f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 15249d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 1525a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 15269d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall IV->getBase()); 15279f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Don't forget the parens to enforce the proper binding. 15288189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), 15298d36616a093f65f667d22bc1136a4c2be0bae7dfChris Lattner IV->getBase()->getLocEnd(), castExpr); 15302b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian replaced = true; 15319f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Cannot delete IV->getBase(), since PE points to it. 15329f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Replace the old base with the cast. This is important when doing 15339f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // embedded rewrites. For example, [newInv->_container addObject:0]. 15341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump IV->setBase(PE); 15359f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff return IV; 15369f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff } 1537c2a689b0bd0cda7bc1522dc0057f01f0897e6d3dSteve Naroff } 153884472a897a99db80d49eb5ac1ac85d54b1cc6554Steve Naroff return IV; 15397e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff} 15407e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff 15412b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz JahanianStmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) { 15427502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) { 15432b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (*CI) { 15442b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced); 15452b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (newStmt) 15462b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian *CI = newStmt; 15472b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian } 15482b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian } 15492b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 15502b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian SourceRange OrigStmtRange = S->getSourceRange(); 15512b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(), 15522b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian replaced); 15532b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian return newStmt; 1554376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian } 1555376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) { 1556376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian Stmt *newStmt = SynthMessageExpr(MsgRefExpr); 1557376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian return newStmt; 1558376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian } 15592b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian return S; 15602b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian} 15612b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian 1562fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// SynthCountByEnumWithState - To print: 1563fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// ((unsigned int (*) 1564fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 15651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// (void *)objc_msgSend)((id)l_collection, 1566fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// sel_registerName( 15671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// "countByEnumeratingWithState:objects:count:"), 15681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// &enumState, 1569fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// (id *)items, (unsigned int)16) 1570fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1571fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroffvoid RewriteObjC::SynthCountByEnumWithState(std::string &buf) { 1572fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 1573fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff "id *, unsigned int))(void *)objc_msgSend)"; 1574fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "\n\t\t"; 1575fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "((id)l_collection,\n\t\t"; 1576fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; 1577fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "\n\t\t"; 1578fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "&enumState, " 1579fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff "(id *)items, (unsigned int)16)"; 1580fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 1581b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff 1582fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach 1583fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// statement to exit to its outer synthesized loop. 1584fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1585fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffStmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) { 1586fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1587fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return S; 1588fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // replace break with goto __break_label 1589fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string buf; 15901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1591fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation startLoc = S->getLocStart(); 1592fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf = "goto __break_label_"; 1593fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += utostr(ObjCBcLabelNo.back()); 1594d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, strlen("break"), buf); 15952bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff 1596fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return 0; 1597fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 1598a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian 1599fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach 1600fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// statement to continue with its inner synthesized loop. 1601fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1602fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffStmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { 1603fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1604fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return S; 1605fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // replace continue with goto __continue_label 1606fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string buf; 16071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1608fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation startLoc = S->getLocStart(); 1609fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf = "goto __continue_label_"; 1610fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += utostr(ObjCBcLabelNo.back()); 1611d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, strlen("continue"), buf); 16121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1613e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian return 0; 1614e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian} 1615e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian 1616a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. 161710d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// It rewrites: 161810d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// for ( type elem in collection) { stmts; } 16191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 162010d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// Into: 162110d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// { 16221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// type elem; 162333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// struct __objcFastEnumerationState enumState = { 0 }; 162410d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// id items[16]; 162533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// id l_collection = (id)collection; 16261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 162733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// objects:items count:16]; 162810d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// if (limit) { 162910d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// unsigned long startMutations = *enumState.mutationsPtr; 163010d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// do { 163110d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// unsigned long counter = 0; 163210d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// do { 16331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if (startMutations != *enumState.mutationsPtr) 163433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// objc_enumerationMutation(l_collection); 163588f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian/// elem = (type)enumState.itemsPtr[counter++]; 163610d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// stmts; 1637e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian/// __continue_label: ; 163810d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } while (counter < limit); 16391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// } while (limit = [l_collection countByEnumeratingWithState:&enumState 164033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// objects:items count:16]); 164133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// elem = nil; 1642e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian/// __break_label: ; 164310d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } 164410d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// else 164510d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// elem = nil; 164610d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } 164710d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// 1648b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 1649338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner SourceLocation OrigEnd) { 1650e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); 16511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 1652e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian "ObjCForCollectionStmt Statement stack mismatch"); 16531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(!ObjCBcLabelNo.empty() && 1654e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian "ObjCForCollectionStmt - Label No stack empty"); 16551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 165633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SourceLocation startLoc = S->getLocStart(); 165733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 16585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef elementName; 165988f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian std::string elementTypeAsString; 166033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian std::string buf; 166133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf = "\n{\n\t"; 166233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) { 166333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // type elem; 16647e24e82a70a2c681f4291a3397bcd1e1005f251aChris Lattner NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl()); 16651ed8e2a39456d064a346a6a5c2f6bd53e6d57345Ted Kremenek QualType ElementType = cast<ValueDecl>(D)->getType(); 1666e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff if (ElementType->isObjCQualifiedIdType() || 1667e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff ElementType->isObjCQualifiedInterfaceType()) 1668e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff // Simply use 'id' for all qualified types. 1669e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff elementTypeAsString = "id"; 1670e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff else 1671fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar elementTypeAsString = ElementType.getAsString(Context->PrintingPolicy); 167288f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += elementTypeAsString; 167333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += " "; 16744087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar elementName = D->getName(); 167533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 167633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ";\n\t"; 167733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian } 167806767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner else { 167906767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); 16804087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar elementName = DR->getDecl()->getName(); 1681e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff ValueDecl *VD = cast<ValueDecl>(DR->getDecl()); 1682e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff if (VD->getType()->isObjCQualifiedIdType() || 1683e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff VD->getType()->isObjCQualifiedInterfaceType()) 1684e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff // Simply use 'id' for all qualified types. 1685e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff elementTypeAsString = "id"; 1686e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff else 1687fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar elementTypeAsString = VD->getType().getAsString(Context->PrintingPolicy); 168888f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian } 16891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 169033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // struct __objcFastEnumerationState enumState = { 0 }; 169133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; 169233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // id items[16]; 169333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "id items[16];\n\t"; 169433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // id l_collection = (id) 169533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "id l_collection = (id)"; 16967571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian // Find start location of 'collection' the hard way! 16977571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian const char *startCollectionBuf = startBuf; 16987571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf += 3; // skip 'for' 16997571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf = strchr(startCollectionBuf, '('); 17007571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf++; // skip '(' 17017571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian // find 'in' and skip it. 17027571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian while (*startCollectionBuf != ' ' || 17037571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' || 17047571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian (*(startCollectionBuf+3) != ' ' && 17057571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) 17067571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf++; 17077571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf += 3; 17081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Replace: "for (type element in" with string constructed thus far. 1710d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, startCollectionBuf - startBuf, buf); 171133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Replace ')' in for '(' type elem in collection ')' with ';' 17127571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian SourceLocation rightParenLoc = S->getRParenLoc(); 17137571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian const char *rparenBuf = SM->getCharacterData(rightParenLoc); 17147571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian SourceLocation lparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf); 171533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf = ";\n\t"; 17161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 171733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 171833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // objects:items count:16]; 171933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // which is synthesized into: 17201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // unsigned int limit = 172133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // ((unsigned int (*) 172233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 17231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // (void *)objc_msgSend)((id)l_collection, 172433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // sel_registerName( 17251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // "countByEnumeratingWithState:objects:count:"), 17261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // (struct __objcFastEnumerationState *)&state, 172733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // (id *)items, (unsigned int)16); 172833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long limit =\n\t\t"; 172933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SynthCountByEnumWithState(buf); 173033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ";\n\t"; 173133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// if (limit) { 173233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// unsigned long startMutations = *enumState.mutationsPtr; 173333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// do { 173433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// unsigned long counter = 0; 173533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// do { 17361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// if (startMutations != *enumState.mutationsPtr) 173733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// objc_enumerationMutation(l_collection); 173888f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian /// elem = (type)enumState.itemsPtr[counter++]; 173933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "if (limit) {\n\t"; 174033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t"; 174133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "do {\n\t\t"; 174233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long counter = 0;\n\t\t"; 174333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "do {\n\t\t\t"; 174433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t"; 174533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "objc_enumerationMutation(l_collection);\n\t\t\t"; 174633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 174788f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += " = ("; 174888f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += elementTypeAsString; 174988f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += ")enumState.itemsPtr[counter++];"; 175033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Replace ')' in for '(' type elem in collection ')' with all of these. 1751d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lparenLoc, 1, buf); 17521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1753e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian /// __continue_label: ; 175433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } while (counter < limit); 17551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// } while (limit = [l_collection countByEnumeratingWithState:&enumState 175633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// objects:items count:16]); 175733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// elem = nil; 1758e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian /// __break_label: ; 175933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } 176033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// else 176133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// elem = nil; 176233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } 17631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// 1764e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf = ";\n\t"; 1765e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "__continue_label_"; 1766e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += utostr(ObjCBcLabelNo.back()); 1767e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += ": ;"; 1768e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "\n\t\t"; 176933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "} while (counter < limit);\n\t"; 177033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "} while (limit = "; 177133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SynthCountByEnumWithState(buf); 177233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ");\n\t"; 177333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 177465b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += " = (("; 177565b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += elementTypeAsString; 177665b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += ")0);\n\t"; 1777e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "__break_label_"; 1778e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += utostr(ObjCBcLabelNo.back()); 1779e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += ": ;\n\t"; 178033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "}\n\t"; 178133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "else\n\t\t"; 178233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 178365b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += " = (("; 178465b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += elementTypeAsString; 178565b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += ")0);\n\t"; 178633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "}\n"; 17871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 178833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Insert all these *after* the statement body. 1789d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // FIXME: If this should support Obj-C++, support CXXTryStmt 1790600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff if (isa<CompoundStmt>(S->getBody())) { 1791600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1); 1792d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endBodyLoc, buf); 1793600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff } else { 1794600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff /* Need to treat single statements specially. For example: 1795600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * 1796600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * for (A *a in b) if (stuff()) break; 1797600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * for (A *a in b) xxxyy; 1798600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * 1799600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * The following code simply scans ahead to the semi to find the actual end. 1800600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff */ 1801600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff const char *stmtBuf = SM->getCharacterData(OrigEnd); 1802600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff const char *semiBuf = strchr(stmtBuf, ';'); 1803600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff assert(semiBuf && "Can't find ';'"); 1804600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(semiBuf-stmtBuf+1); 1805d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endBodyLoc, buf); 1806600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff } 1807e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmts.pop_back(); 1808e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian ObjCBcLabelNo.pop_back(); 180933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return 0; 181010d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian} 181110d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian 18121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// RewriteObjCSynchronizedStmt - 1813a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// This routine rewrites @synchronized(expr) stmt; 1814a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// into: 1815a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// objc_sync_enter(expr); 1816a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// @try stmt @finally { objc_sync_exit(expr); } 1817a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// 1818b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 1819a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian // Get the start location and compute the semi location. 1820a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian SourceLocation startLoc = S->getLocStart(); 1821a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 18221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1823a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian assert((*startBuf == '@') && "bogus @synchronized location"); 18241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string buf; 18263498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff buf = "objc_sync_enter((id)"; 18273498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff const char *lparenBuf = startBuf; 18283498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff while (*lparenBuf != '(') lparenBuf++; 1829d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lparenBuf-startBuf+1, buf); 18301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since 18311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // the sync expression is typically a message expression that's already 1832c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff // been rewritten! (which implies the SourceLocation's are invalid). 1833c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff SourceLocation endLoc = S->getSynchBody()->getLocStart(); 1834a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian const char *endBuf = SM->getCharacterData(endLoc); 1835c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff while (*endBuf != ')') endBuf--; 1836c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff SourceLocation rparenLoc = startLoc.getFileLocWithOffset(endBuf-startBuf); 1837a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf = ");\n"; 1838a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian // declare a new scope with two variables, _stack and _rethrow. 1839a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n"; 1840a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "int buf[18/*32-bit i386*/];\n"; 1841a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "char *pointers[4];} _stack;\n"; 1842a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "id volatile _rethrow = 0;\n"; 1843a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "objc_exception_try_enter(&_stack);\n"; 1844a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 1845d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(rparenLoc, 1, buf); 1846a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian startLoc = S->getSynchBody()->getLocEnd(); 1847a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian startBuf = SM->getCharacterData(startLoc); 18481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1849c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff assert((*startBuf == '}') && "bogus @synchronized block"); 1850a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian SourceLocation lastCurlyLoc = startLoc; 1851a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf = "}\nelse {\n"; 1852a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1853621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff buf += "}\n"; 1854621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff buf += "{ /* implicit finally clause */\n"; 1855a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 1856b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1857b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string syncBuf; 1858b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += " objc_sync_exit("; 18591d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall 18601d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall Expr *syncExpr = S->getSynchExpr(); 18611d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CastKind CK = syncExpr->getType()->isObjCObjectPointerType() 18621d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall ? CK_BitCast : 18631d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall syncExpr->getType()->isBlockPointerType() 18641d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall ? CK_BlockPointerToObjCPointerCast 18651d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall : CK_CPointerToObjCPointerCast; 18661d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 18671d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK, syncExpr); 1868a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string syncExprBufS; 1869a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream syncExprBuf(syncExprBufS); 1870e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner syncExpr->printPretty(syncExprBuf, *Context, 0, 1871e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(LangOpts)); 1872b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += syncExprBuf.str(); 1873b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += ");"; 1874b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1875b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += syncBuf; 1876b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n"; 1877a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "}\n"; 1878a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "}"; 18791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1880d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 1881b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1882b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff bool hasReturns = false; 1883b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(S->getSynchBody(), hasReturns); 1884b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (hasReturns) 1885b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteSyncReturnStmts(S->getSynchBody(), syncBuf); 1886b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1887a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian return 0; 1888a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian} 1889a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian 1890b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S) 1891b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff{ 18928c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff // Perform a bottom up traversal of all children. 18937502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 18948c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff if (*CI) 1895b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff WarnAboutReturnGotoStmts(*CI); 18968c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff 1897b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) { 18981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diags.Report(Context->getFullLoc(S->getLocStart()), 18998c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff TryFinallyContainsReturnDiag); 19008c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff } 19018c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff return; 19028c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff} 19038c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff 1904b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns) 1905b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff{ 1906b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 19077502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 1908b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) 1909b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(*CI, hasReturns); 1910b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1911b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) 1912b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff hasReturns = true; 1913b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1914b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1915b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1916b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::RewriteTryReturnStmts(Stmt *S) { 1917b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 19187502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 1919b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) { 1920b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteTryReturnStmts(*CI); 1921b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1922b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) { 1923b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation startLoc = S->getLocStart(); 1924b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 1925b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1926b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 1927b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'"); 1928b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1); 1929b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1930b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string buf; 1931b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf = "{ objc_exception_try_exit(&_stack); return"; 1932b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1933d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 6, buf); 1934d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, "}"); 1935b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1936b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1937b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1938b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1939b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) { 1940b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 19417502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 1942b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) { 1943b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteSyncReturnStmts(*CI, syncExitBuf); 1944b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1945b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) { 1946b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation startLoc = S->getLocStart(); 1947b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 1948b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1949b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 1950b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'"); 1951b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1); 1952b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1953b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string buf; 1954b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf = "{ objc_exception_try_exit(&_stack);"; 1955b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += syncExitBuf; 1956b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += " return"; 1957b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1958d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 6, buf); 1959d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, "}"); 1960b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1961b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1962b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1963b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1964b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { 19657573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Get the start location and compute the semi location. 19667573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation startLoc = S->getLocStart(); 19677573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 19681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19697573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @try location"); 19707573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 19717573098b83e780d1c5bea13b384b610d8f155676Steve Naroff std::string buf; 19727573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // declare a new scope with two variables, _stack and _rethrow. 19737573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "/* @try scope begin */ { struct _objc_exception_data {\n"; 19747573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "int buf[18/*32-bit i386*/];\n"; 19757573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "char *pointers[4];} _stack;\n"; 19767573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "id volatile _rethrow = 0;\n"; 19777573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "objc_exception_try_enter(&_stack);\n"; 197821867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 19797573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 1980d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 4, buf); 19811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19827573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startLoc = S->getTryBody()->getLocEnd(); 19837573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 19847573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 19857573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '}') && "bogus @try block"); 19861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1987c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff SourceLocation lastCurlyLoc = startLoc; 19888f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (S->getNumCatchStmts()) { 1989c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff startLoc = startLoc.getFileLocWithOffset(1); 1990c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf = " /* @catch begin */ else {\n"; 1991c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " id _caught = objc_exception_extract(&_stack);\n"; 1992c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " objc_exception_try_enter (&_stack);\n"; 1993c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " if (_setjmp(_stack.buf))\n"; 1994c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1995c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " else { /* @catch continue */"; 19961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1997d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, buf); 19988bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff } else { /* no catch list */ 19998bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf = "}\nelse {\n"; 20008bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf += " _rethrow = objc_exception_extract(&_stack);\n"; 20018bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf += "}"; 2002d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 2003c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff } 20047573098b83e780d1c5bea13b384b610d8f155676Steve Naroff Stmt *lastCatchBody = 0; 20058f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { 20068f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor ObjCAtCatchStmt *Catch = S->getCatchStmt(I); 2007c00d8e18ad3d903acfeb5d05163ce90713066a3fDouglas Gregor VarDecl *catchDecl = Catch->getCatchParamDecl(); 20087573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 20098f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (I == 0) 20107573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "if ("; // we are generating code for the first catch clause 20117573098b83e780d1c5bea13b384b610d8f155676Steve Naroff else 20127573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "else if ("; 20138f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor startLoc = Catch->getLocStart(); 20147573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 20151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20167573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @catch location"); 20171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20187573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *lParenLoc = strchr(startBuf, '('); 20197573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 20208f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (Catch->hasEllipsis()) { 2021e12e69223ec279e89ac681023d42184b115e0068Steve Naroff // Now rewrite the body... 20228f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor lastCatchBody = Catch->getCatchBody(); 2023e12e69223ec279e89ac681023d42184b115e0068Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocStart(); 2024e12e69223ec279e89ac681023d42184b115e0068Steve Naroff const char *bodyBuf = SM->getCharacterData(bodyLoc); 20258f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' && 202606767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @catch paren location"); 2027e12e69223ec279e89ac681023d42184b115e0068Steve Naroff assert((*bodyBuf == '{') && "bogus @catch body location"); 20281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2029e12e69223ec279e89ac681023d42184b115e0068Steve Naroff buf += "1) { id _tmp = _caught;"; 2030d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf); 20317ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff } else if (catchDecl) { 20327ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff QualType t = catchDecl->getType(); 2033a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (t == Context->getObjCIdType()) { 20347573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "1) { "; 2035d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 2036506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall } else if (const ObjCObjectPointerType *Ptr = 2037506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall t->getAs<ObjCObjectPointerType>()) { 2038506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall // Should be a pointer to a class. 2039506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface(); 2040506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall if (IDecl) { 204121867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; 2042506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall buf += IDecl->getNameAsString(); 204321867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "\"), (struct objc_object *)_caught)) { "; 2044d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 20457573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 20467573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 20477573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Now rewrite the body... 20488f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor lastCatchBody = Catch->getCatchBody(); 20498f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor SourceLocation rParenLoc = Catch->getRParenLoc(); 20507573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocStart(); 20517573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *bodyBuf = SM->getCharacterData(bodyLoc); 20527573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *rParenBuf = SM->getCharacterData(rParenLoc); 20537573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*rParenBuf == ')') && "bogus @catch paren location"); 20547573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*bodyBuf == '{') && "bogus @catch body location"); 20551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Here we replace ") {" with "= _caught;" (which initializes and 20577573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // declares the @catch parameter). 2058d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;"); 20597ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff } else { 20607573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert(false && "@catch rewrite bug"); 20612bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff } 20627573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 20637573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Complete the catch list... 20647573098b83e780d1c5bea13b384b610d8f155676Steve Naroff if (lastCatchBody) { 20657573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocEnd(); 206606767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner assert(*SM->getCharacterData(bodyLoc) == '}' && 206706767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @catch body location"); 20681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2069378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff // Insert the last (implicit) else clause *before* the right curly brace. 2070378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff bodyLoc = bodyLoc.getFileLocWithOffset(-1); 2071378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf = "} /* last catch end */\n"; 2072378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "else {\n"; 2073378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " _rethrow = _caught;\n"; 2074378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " objc_exception_try_exit(&_stack);\n"; 2075378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "} } /* @catch end */\n"; 2076378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff if (!S->getFinallyStmt()) 2077378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "}\n"; 2078d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(bodyLoc, buf); 20791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20807573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Set lastCurlyLoc 20817573098b83e780d1c5bea13b384b610d8f155676Steve Naroff lastCurlyLoc = lastCatchBody->getLocEnd(); 20827573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 2083a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) { 20847573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startLoc = finalStmt->getLocStart(); 20857573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 20867573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @finally start"); 20871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2088d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 8, "/* @finally */"); 20891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20907573098b83e780d1c5bea13b384b610d8f155676Steve Naroff Stmt *body = finalStmt->getFinallyBody(); 20917573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation startLoc = body->getLocStart(); 20927573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation endLoc = body->getLocEnd(); 209306767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner assert(*SM->getCharacterData(startLoc) == '{' && 209406767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @finally body location"); 20951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(*SM->getCharacterData(endLoc) == '}' && 209606767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @finally body location"); 20971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20987573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startLoc = startLoc.getFileLocWithOffset(1); 2099d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n"); 21007573098b83e780d1c5bea13b384b610d8f155676Steve Naroff endLoc = endLoc.getFileLocWithOffset(-1); 2101d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n"); 21021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21037573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Set lastCurlyLoc 21047573098b83e780d1c5bea13b384b610d8f155676Steve Naroff lastCurlyLoc = body->getLocEnd(); 21051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21068c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff // Now check for any return/continue/go statements within the @try. 2107b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff WarnAboutReturnGotoStmts(S->getTryBody()); 2108378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff } else { /* no finally clause - make sure we synthesize an implicit one */ 2109378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf = "{ /* implicit finally clause */\n"; 2110378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 2111378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; 2112378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "}"; 2113d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 2114b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 2115b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Now check for any return/continue/go statements within the @try. 2116b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // The implicit finally clause won't called if the @try contains any 2117b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // jump statements. 2118b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff bool hasReturns = false; 2119b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(S->getTryBody(), hasReturns); 2120b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (hasReturns) 2121b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteTryReturnStmts(S->getTryBody()); 21227573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 21237573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Now emit the final closing curly brace... 21247573098b83e780d1c5bea13b384b610d8f155676Steve Naroff lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1); 2125d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(lastCurlyLoc, " } /* @try scope end */\n"); 2126909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian return 0; 2127909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian} 2128909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian 21291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// This can't be done with ReplaceStmt(S, ThrowExpr), since 21301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// the throw expression is typically a message expression that's already 21312bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff// been rewritten! (which implies the SourceLocation's are invalid). 2132b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { 21332bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff // Get the start location and compute the semi location. 21342bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff SourceLocation startLoc = S->getLocStart(); 21352bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff const char *startBuf = SM->getCharacterData(startLoc); 21361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21372bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff assert((*startBuf == '@') && "bogus @throw location"); 21382bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff 21392bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff std::string buf; 21402bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff /* void objc_exception_throw(id) __attribute__((noreturn)); */ 214120ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff if (S->getThrowExpr()) 214220ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff buf = "objc_exception_throw("; 214320ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff else // add an implicit argument 214420ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff buf = "objc_exception_throw(_caught"; 21451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21464ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff // handle "@ throw" correctly. 21474ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff const char *wBuf = strchr(startBuf, 'w'); 21484ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff assert((*wBuf == 'w') && "@throw: can't find 'w'"); 2149d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, wBuf-startBuf+1, buf); 21501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21512bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff const char *semiBuf = strchr(startBuf, ';'); 21522bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff assert((*semiBuf == ';') && "@throw: can't find ';'"); 21532bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf); 2154d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(semiLoc, 1, ");"); 21552bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff return 0; 21562bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff} 2157909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian 2158b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { 215901c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner // Create a new string expression. 216001c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner QualType StrType = Context->getPointerType(Context->CharTy); 216185f9bceab1542aafff012d4d28e998f4ba16e362Anders Carlsson std::string StrEncoding; 21620d504c1da852e58ff802545c823ecff3b6c654b8Daniel Dunbar Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); 216365aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad Expr *Replacement = StringLiteral::Create(*Context, StrEncoding, 21645cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 21655cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StrType, SourceLocation()); 2166dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, Replacement); 21671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21680750618b0beacdc9b0a9e210a661e4746823ced7Chris Lattner // Replace this subexpr in the parent. 2169f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2170e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner return Replacement; 2171311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner} 2172311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner 2173b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { 21741a9376408941d65c285ddad8a0f1a2ac518df344Steve Naroff if (!SelGetUidFunctionDecl) 21751a9376408941d65c285ddad8a0f1a2ac518df344Steve Naroff SynthSelGetUidFunctionDecl(); 2176b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl"); 2177b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff // Create a call to sel_registerName("selName"). 21785f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> SelExprs; 2179b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff QualType argType = Context->getPointerType(Context->CharTy); 21801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SelExprs.push_back(StringLiteral::Create(*Context, 218165aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad Exp->getSelector().getAsString(), 21825cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 21835cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor argType, SourceLocation())); 2184b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 2185b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff &SelExprs[0], SelExprs.size()); 2186dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, SelExp); 2187f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2188b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff return SelExp; 2189b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff} 2190b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff 2191b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffCallExpr *RewriteObjC::SynthesizeCallToFunctionDecl( 21921d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc, 21931d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc) { 2194ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Get the type, we will need to reference it in a couple spots. 2195934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff QualType msgSendType = FD->getType(); 21961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2197ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Create a reference to the objc_msgSend() declaration. 2198f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExpr *DRE = 2199f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall new (Context) DeclRefExpr(FD, msgSendType, VK_LValue, SourceLocation()); 22001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2201ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Now, we cast the reference to a pointer to the objc_msgSend type. 2202f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner QualType pToFunc = Context->getPointerType(msgSendType); 220388465d3e996e627bbaa11099b039ddab66d5af2cAnders Carlsson ImplicitCastExpr *ICE = 2204a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, 22055baba9d98364a3525d6afa15a04cdad82fd6dd30John McCall DRE, 0, VK_RValue); 22061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2207183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *FT = msgSendType->getAs<FunctionType>(); 22081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22091d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian CallExpr *Exp = 22105291c3cec0dbe8ad1d8e7e67e93af2b1586d5400Douglas Gregor new (Context) CallExpr(*Context, ICE, args, nargs, 2211f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FT->getCallResultType(*Context), 2212f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, EndLoc); 22131d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian return Exp; 2214934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff} 2215934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff 2216d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroffstatic bool scanForProtocolRefs(const char *startBuf, const char *endBuf, 2217d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *&startRef, const char *&endRef) { 2218d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff while (startBuf < endBuf) { 2219d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (*startBuf == '<') 2220d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startRef = startBuf; // mark the start. 2221d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (*startBuf == '>') { 222232174826f58d38c20f376fe64ceac4a278133883Steve Naroff if (startRef && *startRef == '<') { 222332174826f58d38c20f376fe64ceac4a278133883Steve Naroff endRef = startBuf; // mark the end. 222432174826f58d38c20f376fe64ceac4a278133883Steve Naroff return true; 222532174826f58d38c20f376fe64ceac4a278133883Steve Naroff } 222632174826f58d38c20f376fe64ceac4a278133883Steve Naroff return false; 2227d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2228d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startBuf++; 2229d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2230d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff return false; 2231d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff} 2232d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff 223361477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanianstatic void scanToNextArgument(const char *&argRef) { 223461477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian int angle = 0; 223561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian while (*argRef != ')' && (*argRef != ',' || angle > 0)) { 223661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (*argRef == '<') 223761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian angle++; 223861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else if (*argRef == '>') 223961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian angle--; 224061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian argRef++; 224161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 224261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian assert(angle == 0 && "scanToNextArgument - bad protocol type syntax"); 224361477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian} 2244291e04b29669d6576e19e35555bbc3cadd2f6649Fariborz Jahanian 2245b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffbool RewriteObjC::needToScanForQualifiers(QualType T) { 224632132a08c0aecc316728d81e1d93726707fde14bFariborz Jahanian if (T->isObjCQualifiedIdType()) 224732132a08c0aecc316728d81e1d93726707fde14bFariborz Jahanian return true; 224884aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (const PointerType *PT = T->getAs<PointerType>()) { 224984aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (PT->getPointeeType()->isObjCQualifiedIdType()) 225084aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return true; 225184aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian } 225284aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (T->isObjCObjectPointerType()) { 225384aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian T = T->getPointeeType(); 225484aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return T->isObjCQualifiedInterfaceType(); 225584aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian } 225624f9cab9288368171caaef4bb18b95e4f6083f22Fariborz Jahanian if (T->isArrayType()) { 225724f9cab9288368171caaef4bb18b95e4f6083f22Fariborz Jahanian QualType ElemTy = Context->getBaseElementType(T); 225824f9cab9288368171caaef4bb18b95e4f6083f22Fariborz Jahanian return needToScanForQualifiers(ElemTy); 225924f9cab9288368171caaef4bb18b95e4f6083f22Fariborz Jahanian } 226084aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return false; 2261d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff} 2262d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff 22634f95b750534f2111f28434b282bcbd5656002816Steve Naroffvoid RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { 22644f95b750534f2111f28434b282bcbd5656002816Steve Naroff QualType Type = E->getType(); 22654f95b750534f2111f28434b282bcbd5656002816Steve Naroff if (needToScanForQualifiers(Type)) { 2266cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff SourceLocation Loc, EndLoc; 22671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2268cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { 2269cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff Loc = ECE->getLParenLoc(); 2270cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff EndLoc = ECE->getRParenLoc(); 2271cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff } else { 2272cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff Loc = E->getLocStart(); 2273cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff EndLoc = E->getLocEnd(); 2274cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff } 2275cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff // This will defend against trying to rewrite synthesized expressions. 2276cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff if (Loc.isInvalid() || EndLoc.isInvalid()) 2277cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff return; 2278cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff 22794f95b750534f2111f28434b282bcbd5656002816Steve Naroff const char *startBuf = SM->getCharacterData(Loc); 2280cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff const char *endBuf = SM->getCharacterData(EndLoc); 22814f95b750534f2111f28434b282bcbd5656002816Steve Naroff const char *startRef = 0, *endRef = 0; 22824f95b750534f2111f28434b282bcbd5656002816Steve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 22834f95b750534f2111f28434b282bcbd5656002816Steve Naroff // Get the locations of the startRef, endRef. 22844f95b750534f2111f28434b282bcbd5656002816Steve Naroff SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf); 22854f95b750534f2111f28434b282bcbd5656002816Steve Naroff SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1); 22864f95b750534f2111f28434b282bcbd5656002816Steve Naroff // Comment out the protocol references. 2287d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2288d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 22894f95b750534f2111f28434b282bcbd5656002816Steve Naroff } 22904f95b750534f2111f28434b282bcbd5656002816Steve Naroff } 22914f95b750534f2111f28434b282bcbd5656002816Steve Naroff} 22924f95b750534f2111f28434b282bcbd5656002816Steve Naroff 2293b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { 229461477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian SourceLocation Loc; 229561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian QualType Type; 229672564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *proto = 0; 229761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) { 229861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Loc = VD->getLocation(); 229961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Type = VD->getType(); 230061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 230161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) { 230261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Loc = FD->getLocation(); 230361477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // Check for ObjC 'id' and class types that have been adorned with protocol 230461477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // information (id<p>, C<p>*). The protocol references need to be rewritten! 2305183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 230661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian assert(funcType && "missing function type"); 230772564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor proto = dyn_cast<FunctionProtoType>(funcType); 230861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (!proto) 230961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian return; 231061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Type = proto->getResultType(); 231161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 23123d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) { 23133d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff Loc = FD->getLocation(); 23143d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff Type = FD->getType(); 23153d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff } 231661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else 2317e66894c3dea9aeab4403e67bf5baabc20da61cb3Fariborz Jahanian return; 23181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 231961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (needToScanForQualifiers(Type)) { 2320d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Since types are unique, we need to scan the buffer. 23211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2322d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *endBuf = SM->getCharacterData(Loc); 2323d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startBuf = endBuf; 23246cafbf2a678c95d4cdc09ecaa782319bbcf56944Steve Naroff while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) 2325d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startBuf--; // scan backward (from the decl location) for return type. 2326d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startRef = 0, *endRef = 0; 2327d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2328d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Get the locations of the startRef, endRef. 2329d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf); 2330d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1); 2331d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Comment out the protocol references. 2332d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2333d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 2334d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2335d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 233661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (!proto) 233761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian return; // most likely, was a variable 23389165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff // Now check arguments. 233961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian const char *startBuf = SM->getCharacterData(Loc); 234061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian const char *startFuncBuf = startBuf; 23419165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff for (unsigned i = 0; i < proto->getNumArgs(); i++) { 2342d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (needToScanForQualifiers(proto->getArgType(i))) { 2343d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Since types are unique, we need to scan the buffer. 23441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2345d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *endBuf = startBuf; 234661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // scan forward (from the decl location) for argument types. 234761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian scanToNextArgument(endBuf); 2348d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startRef = 0, *endRef = 0; 2349d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2350d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Get the locations of the startRef, endRef. 23511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation LessLoc = 2352291e04b29669d6576e19e35555bbc3cadd2f6649Fariborz Jahanian Loc.getFileLocWithOffset(startRef-startFuncBuf); 23531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation GreaterLoc = 2354291e04b29669d6576e19e35555bbc3cadd2f6649Fariborz Jahanian Loc.getFileLocWithOffset(endRef-startFuncBuf+1); 2355d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Comment out the protocol references. 2356d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2357d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 2358d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 235961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf = ++endBuf; 236061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 236161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else { 2362aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff // If the function name is derived from a macro expansion, then the 2363aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff // argument buffer will not follow the name. Need to speak with Chris. 2364aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff while (*startBuf && *startBuf != ')' && *startBuf != ',') 236561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf++; // scan forward (from the decl location) for argument types. 236661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf++; 236761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 23689165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff } 23699165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff} 23709165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff 23714c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanianvoid RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) { 23724c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian QualType QT = ND->getType(); 23734c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const Type* TypePtr = QT->getAs<Type>(); 23744c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (!isa<TypeOfExprType>(TypePtr)) 23754c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian return; 23764c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian while (isa<TypeOfExprType>(TypePtr)) { 23774c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 23784c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 23794c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian TypePtr = QT->getAs<Type>(); 23804c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 23814c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian // FIXME. This will not work for multiple declarators; as in: 23824c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian // __typeof__(a) b,c,d; 2383fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string TypeAsString(QT.getAsString(Context->PrintingPolicy)); 23844c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 23854c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *startBuf = SM->getCharacterData(DeclLoc); 23864c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (ND->getInit()) { 23874c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian std::string Name(ND->getNameAsString()); 23884c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian TypeAsString += " " + Name + " = "; 23894c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian Expr *E = ND->getInit(); 23904c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation startLoc; 23914c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 23924c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian startLoc = ECE->getLParenLoc(); 23934c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian else 23944c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian startLoc = E->getLocStart(); 2395402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth startLoc = SM->getExpansionLoc(startLoc); 23964c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *endBuf = SM->getCharacterData(startLoc); 2397d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 23984c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 23994c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian else { 24004c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation X = ND->getLocEnd(); 2401402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth X = SM->getExpansionLoc(X); 24024c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *endBuf = SM->getCharacterData(X); 2403d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 24044c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 24054c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian} 24064c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian 2407a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); 2408b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthSelGetUidFunctionDecl() { 2409a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); 24105f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 24110953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2412e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getFuncType = 2413e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size()); 2414ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2416ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2417a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis SelGetUidIdent, getFuncType, 0, 2418d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2419d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 2420a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian} 2421a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian 2422b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { 242309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff // declared in <objc/objc.h> 242451efe56116a6283ba707cfb8bf8b4e0b13cb41acDouglas Gregor if (FD->getIdentifier() && 24254087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FD->getName() == "sel_registerName") { 242609b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SelGetUidFunctionDecl = FD; 24279165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff return; 24289165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff } 2429a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCQualifiedInterfaceTypes(FD); 243009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 243109b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2432fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbarvoid RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) { 2433fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string TypeString(Type.getAsString(Context->PrintingPolicy)); 243452b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian const char *argPtr = TypeString.c_str(); 243552b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian if (!strchr(argPtr, '^')) { 243652b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian Str += TypeString; 243752b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian return; 243852b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian } 243952b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian while (*argPtr) { 244052b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian Str += (*argPtr == '^' ? '*' : *argPtr); 244152b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian argPtr++; 244252b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian } 244352b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian} 244452b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian 2445e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian// FIXME. Consolidate this routine with RewriteBlockPointerType. 2446fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbarvoid RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str, 2447fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ValueDecl *VD) { 2448e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian QualType Type = VD->getType(); 2449fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string TypeString(Type.getAsString(Context->PrintingPolicy)); 2450e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian const char *argPtr = TypeString.c_str(); 2451e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian int paren = 0; 2452e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian while (*argPtr) { 2453e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian switch (*argPtr) { 2454e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case '(': 2455e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2456e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian paren++; 2457e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2458e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case ')': 2459e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2460e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian paren--; 2461e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2462e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case '^': 2463e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += '*'; 2464e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian if (paren == 1) 2465e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += VD->getNameAsString(); 2466e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2467e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian default: 2468e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2469e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2470e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 2471e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian argPtr++; 2472e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 2473e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian} 2474e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian 2475e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian 2476abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanianvoid RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { 2477abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 2478abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 2479abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType); 2480abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian if (!proto) 2481abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian return; 2482abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian QualType Type = proto->getResultType(); 2483fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string FdStr = Type.getAsString(Context->PrintingPolicy); 2484abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += " "; 24854087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FdStr += FD->getName(); 2486abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += "("; 2487abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian unsigned numArgs = proto->getNumArgs(); 2488abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian for (unsigned i = 0; i < numArgs; i++) { 2489abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian QualType ArgType = proto->getArgType(i); 249052b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian RewriteBlockPointerType(FdStr, ArgType); 2491abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian if (i+1 < numArgs) 2492abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += ", "; 2493abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian } 2494abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += ");\n"; 2495d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, FdStr); 2496abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 2497abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian} 2498abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian 2499c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff// SynthSuperContructorFunctionDecl - id objc_super(id obj, id super); 2500b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthSuperContructorFunctionDecl() { 2501c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff if (SuperContructorFunctionDecl) 2502c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff return; 250346a98a7df016b4a6835a1902c2f8ff2a3a8012baSteve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super"); 25045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2505c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff QualType argT = Context->getObjCIdType(); 2506c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff assert(!argT.isNull() && "Can't find 'id' type"); 2507c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff ArgTys.push_back(argT); 2508c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff ArgTys.push_back(argT); 2509e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2510e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size()); 2511ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2513ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2514a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2515d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2516d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 2517c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff} 2518c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff 251909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); 2520b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendFunctionDecl() { 252109b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend"); 25225f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2523a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 252409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff assert(!argT.isNull() && "Can't find 'id' type"); 252509b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff ArgTys.push_back(argT); 2526a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 252709b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff assert(!argT.isNull() && "Can't find 'SEL' type"); 252809b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff ArgTys.push_back(argT); 2529e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2530e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2531e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2532ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25330ed844b04ea4387caa4e1cf3dc375d269657536bChris Lattner SourceLocation(), 2534ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2535a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2536d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2537d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 253809b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 253909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2540874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...); 2541b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendSuperFunctionDecl() { 2542874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); 25435f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2544465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2545ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 2546df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 2547874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 2548874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 2549874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff ArgTys.push_back(argT); 2550a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 2551874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff assert(!argT.isNull() && "Can't find 'SEL' type"); 2552874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff ArgTys.push_back(argT); 2553e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2554e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2555e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2556ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2558ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2559a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2560d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2561d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 2562874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff} 2563874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff 256480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); 2565b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendStretFunctionDecl() { 256680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret"); 25675f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2568a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 256980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'id' type"); 257080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2571a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 257280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 257380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2574e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2575e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2576e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2577ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2579ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2580a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2581d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2582d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 258380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian} 258480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian 25851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// SynthMsgSendSuperStretFunctionDecl - 258680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...); 2587b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { 25881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump IdentifierInfo *msgSendIdent = 258980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian &Context->Idents.get("objc_msgSendSuper_stret"); 25905f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2591465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2592ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 2593df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 259480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 259580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 259680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2597a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 259880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 259980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2600e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2601e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2602e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2603ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 26041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2605ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2606a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2607d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2608d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 260980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian} 261080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian 26111284db8d85782c4eb1d41eb02358613c8681f07fSteve Naroff// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); 2612b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendFpretFunctionDecl() { 2613acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret"); 26145f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2615a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 2616acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian assert(!argT.isNull() && "Can't find 'id' type"); 2617acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian ArgTys.push_back(argT); 2618a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 2619acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 2620acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian ArgTys.push_back(argT); 2621e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, 2622e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2623e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2624ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 26251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2626ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2627a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2628d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2629d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 2630acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian} 2631acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian 263209b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff// SynthGetClassFunctionDecl - id objc_getClass(const char *name); 2633b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthGetClassFunctionDecl() { 263409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); 26355f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 26360953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2637e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), 2638e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size()); 2639ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 26401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2641ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2642a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis getClassIdent, getClassType, 0, 2643d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2644d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 264509b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 264609b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2647d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); 2648d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanianvoid RewriteObjC::SynthGetSuperClassFunctionDecl() { 2649d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian IdentifierInfo *getSuperClassIdent = 2650d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian &Context->Idents.get("class_getSuperclass"); 26515f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2652d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian ArgTys.push_back(Context->getObjCClassType()); 2653e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 2654e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size()); 2655d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 265616573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor SourceLocation(), 2657ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 265816573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor getSuperClassIdent, 265916573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor getClassType, 0, 2660d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2661d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, 266216573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor false); 2663d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian} 2664d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian 26659bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name); 2666b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthGetMetaClassFunctionDecl() { 26679bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); 26685f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 26690953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2670e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), 2671e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size()); 2672ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 26731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2674ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2675a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis getClassIdent, getClassType, 0, 2676d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2677d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 26789bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff} 26799bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff 2680b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { 2681d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff QualType strType = getConstantStringStructType(); 2682d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 2683d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff std::string S = "__NSConstantStringImpl_"; 26847691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff 26857691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff std::string tmpName = InFileName; 26867691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff unsigned i; 26877691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff for (i=0; i < tmpName.length(); i++) { 26887691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff char c = tmpName.at(i); 26897691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff // replace any non alphanumeric characters with '_'. 26907691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff if (!isalpha(c) && (c < '0' || c > '9')) 26917691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff tmpName[i] = '_'; 26927691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff } 26937691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff S += tmpName; 26947691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff S += "_"; 2695d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff S += utostr(NumObjCStringLiterals++); 2696d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 2697ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "static __NSConstantStringImpl " + S; 2698ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,"; 2699ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "0x000007c8,"; // utf8_str 2700d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // The pretty printer for StringLiteral handles escape characters properly. 2701a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string prettyBufS; 2702a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream prettyBuf(prettyBufS); 2703e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner Exp->getString()->printPretty(prettyBuf, *Context, 0, 2704e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(LangOpts)); 2705ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += prettyBuf.str(); 2706ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += ","; 2707fd5b76fe99a123630321b45667a78f1a15be7241Steve Naroff Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; 27081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 27091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 2710ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), &Context->Idents.get(S), 2711ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara strType, 0, SC_Static, SC_None); 2712f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, VK_LValue, 2713f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 27142de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, 27151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Context->getPointerType(DRE->getType()), 2716f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 2717f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 27189698464266660346fa2da1bddc3e6404a9819b25Steve Naroff // cast to NSConstantString * 27199d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), 27201d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK_CPointerToObjCPointerCast, Unop); 2721dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, cast); 2722f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 27239698464266660346fa2da1bddc3e6404a9819b25Steve Naroff return cast; 2724beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff} 2725beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff 2726874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff// struct objc_super { struct objc_object *receiver; struct objc_class *super; }; 2727b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffQualType RewriteObjC::getSuperStructType() { 2728874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff if (!SuperStructDecl) { 2729465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2730ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 2731df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 2732874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType FieldTypes[2]; 27331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2734874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // struct objc_object *receiver; 27351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[0] = Context->getObjCIdType(); 2736874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // struct objc_class *super; 27371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[1] = Context->getObjCClassType(); 273844b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2739874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // Create fields 274044b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor for (unsigned i = 0; i < 2; ++i) { 27411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, 2742ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 27431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 0, 2744a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis FieldTypes[i], 0, 2745a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis /*BitWidth=*/0, 27467a614d8380297fcd2bc23986241905d97222948cRichard Smith /*Mutable=*/false, 27477a614d8380297fcd2bc23986241905d97222948cRichard Smith /*HasInit=*/false)); 274844b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor } 27491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2750838db383b69b9fb55f55c8e9546477df198a4faaDouglas Gregor SuperStructDecl->completeDefinition(); 2751874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } 2752874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff return Context->getTagDeclType(SuperStructDecl); 2753874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff} 2754874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff 2755b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffQualType RewriteObjC::getConstantStringStructType() { 2756d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff if (!ConstantStringDecl) { 2757465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2758ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 2759df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("__NSConstantStringImpl")); 2760d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff QualType FieldTypes[4]; 27611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2762d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // struct objc_object *receiver; 27631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[0] = Context->getObjCIdType(); 2764d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // int flags; 27651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[1] = Context->IntTy; 2766d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // char *str; 27671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[2] = Context->getPointerType(Context->CharTy); 2768d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // long length; 27691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[3] = Context->LongTy; 277044b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2771d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // Create fields 277244b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor for (unsigned i = 0; i < 4; ++i) { 27731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConstantStringDecl->addDecl(FieldDecl::Create(*Context, 27741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConstantStringDecl, 2775ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 277644b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor SourceLocation(), 0, 2777a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis FieldTypes[i], 0, 277844b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor /*BitWidth=*/0, 27797a614d8380297fcd2bc23986241905d97222948cRichard Smith /*Mutable=*/true, 27807a614d8380297fcd2bc23986241905d97222948cRichard Smith /*HasInit=*/false)); 278144b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor } 278244b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2783838db383b69b9fb55f55c8e9546477df198a4faaDouglas Gregor ConstantStringDecl->completeDefinition(); 2784d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff } 2785d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff return Context->getTagDeclType(ConstantStringDecl); 2786d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff} 2787d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 27881d35b168348a308696d1fce29a18c14143f61d6aFariborz JahanianStmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 27891d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation StartLoc, 27901d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc) { 2791a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian if (!SelGetUidFunctionDecl) 2792a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian SynthSelGetUidFunctionDecl(); 279309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff if (!MsgSendFunctionDecl) 279409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SynthMsgSendFunctionDecl(); 2795874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff if (!MsgSendSuperFunctionDecl) 2796874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff SynthMsgSendSuperFunctionDecl(); 279780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (!MsgSendStretFunctionDecl) 279880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SynthMsgSendStretFunctionDecl(); 279980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (!MsgSendSuperStretFunctionDecl) 280080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SynthMsgSendSuperStretFunctionDecl(); 2801acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian if (!MsgSendFpretFunctionDecl) 2802acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian SynthMsgSendFpretFunctionDecl(); 280309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff if (!GetClassFunctionDecl) 280409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SynthGetClassFunctionDecl(); 2805d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian if (!GetSuperClassFunctionDecl) 2806d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian SynthGetSuperClassFunctionDecl(); 28079bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff if (!GetMetaClassFunctionDecl) 28089bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff SynthGetMetaClassFunctionDecl(); 28091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2810874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // default to objc_msgSend(). 281180a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 281280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // May need to use objc_msgSend_stret() as well. 281380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendStretFlavor = 0; 2814621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { 2815621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QualType resultType = mDecl->getResultType(); 2816fb87b89fc9eb103e19fb8e4b925c23f0bd091b99Douglas Gregor if (resultType->isRecordType()) 281780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian MsgSendStretFlavor = MsgSendStretFunctionDecl; 28188b51fd76319d8b71f401cc6ad56e6f4f7be77958Chris Lattner else if (resultType->isRealFloatingType()) 2819acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian MsgSendFlavor = MsgSendFpretFunctionDecl; 282080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian } 28211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2822934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Synthesize a call to objc_msgSend(). 28235f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> MsgExprs; 282404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor switch (Exp->getReceiverKind()) { 282504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::SuperClass: { 282604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendFlavor = MsgSendSuperFunctionDecl; 282704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (MsgSendStretFlavor) 282804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 282904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 283004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 283104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 283204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 28335f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 4> InitExprs; 283404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 283504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // set the receiver to self, the first argument to all methods. 283604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 283704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2838a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 283904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 2840f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Context->getObjCIdType(), 2841f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, 2842f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation())) 284304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ); // set the 'receiver'. 284404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 284504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 28465f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> ClsExprs; 284704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 284804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 284965aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad ClassDecl->getIdentifier()->getName(), 28505cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 28515cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor argType, SourceLocation())); 285204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, 285304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 285404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 285504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, 285604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor EndLoc); 285704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (Class)objc_getClass("CurrentClass") 285804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 285904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCClassType(), 28601d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK_CPointerToObjCPointerCast, Cls); 286104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.clear(); 286204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(ArgExpr); 286304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 286404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], ClsExprs.size(), 286504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 286604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 286704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 286804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // To turn off a warning, type-cast to 'id' 286904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( // set 'super class', using class_getSuperclass(). 287004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, 287104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCIdType(), 2872a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, Cls)); 287304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super 287404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType superType = getSuperStructType(); 287504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *SuperRep; 287604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 287704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (LangOpts.Microsoft) { 287804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SynthSuperContructorFunctionDecl(); 287904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Simulate a contructor call... 288004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, 2881f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, 2882f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 288304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], 288404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.size(), 2885f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, 2886f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 288704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // The code for super is a little tricky to prevent collision with 288804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // the structure definition in the header. The rewriter has it's own 288904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // internal definition (__rw_objc_super) that is uses. This is why 289004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // we need the cast below. For example: 289104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 289204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // 28932de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 289404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 2895f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 2896f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 289704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = NoTypeInfoCStyleCastExpr(Context, 289804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(superType), 2899a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, SuperRep); 29009bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff } else { 290104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super) { <exprs from above> } 290204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitListExpr *ILE = 290304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) InitListExpr(*Context, SourceLocation(), 290404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &InitExprs[0], InitExprs.size(), 290504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 290604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor TypeSourceInfo *superTInfo 290704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor = Context->getTrivialTypeSourceInfo(superType); 290804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 2909f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, 2910f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall ILE, false); 291104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super * 29122de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 291304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 2914f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 2915f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 29169bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff } 291704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(SuperRep); 291804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 291904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 292004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 292104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::Class: { 29225f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> ClsExprs; 292304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 292404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *Class 2925506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface(); 292604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor IdentifierInfo *clsName = Class->getIdentifier(); 292704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 292865aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad clsName->getName(), 29295cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 29303e2193ce5feb2feb092e5ae615e85148e06e9fd2Anders Carlsson argType, SourceLocation())); 293104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 293204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 293304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 293404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 293504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(Cls); 293604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 293704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 293804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 293904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::SuperInstance:{ 294004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendFlavor = MsgSendSuperFunctionDecl; 294104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (MsgSendStretFlavor) 294204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 294304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 294404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 29455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 4> InitExprs; 294604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 294704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 294804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2949a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 295004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 2951f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Context->getObjCIdType(), 2952f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, SourceLocation())) 295304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ); // set the 'receiver'. 295404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 295504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 29565f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> ClsExprs; 295704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 295804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 295965aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad ClassDecl->getIdentifier()->getName(), 29605cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, argType, 29615cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor SourceLocation())); 296204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 296304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 296404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 296504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 296604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (Class)objc_getClass("CurrentClass") 296704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 296804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCClassType(), 2969a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, Cls); 297004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.clear(); 297104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(ArgExpr); 297204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 297304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], ClsExprs.size(), 297404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 297504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 297604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 297704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // To turn off a warning, type-cast to 'id' 297804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 297904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // set 'super class', using class_getSuperclass(). 298004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2981a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, Cls)); 298204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super 298304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType superType = getSuperStructType(); 298404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *SuperRep; 298504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 298604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (LangOpts.Microsoft) { 298704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SynthSuperContructorFunctionDecl(); 298804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Simulate a contructor call... 298904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, 2990f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, 2991f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 299204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], 299304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.size(), 2994f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, SourceLocation()); 299504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // The code for super is a little tricky to prevent collision with 299604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // the structure definition in the header. The rewriter has it's own 299704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // internal definition (__rw_objc_super) that is uses. This is why 299804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // we need the cast below. For example: 299904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 300004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // 30012de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 300204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 3003f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 300404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 300504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = NoTypeInfoCStyleCastExpr(Context, 300604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(superType), 3007a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, SuperRep); 3008874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } else { 300904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super) { <exprs from above> } 301004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitListExpr *ILE = 301104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) InitListExpr(*Context, SourceLocation(), 301204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &InitExprs[0], InitExprs.size(), 301304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 301404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor TypeSourceInfo *superTInfo 301504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor = Context->getTrivialTypeSourceInfo(superType); 301604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 3017f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_RValue, ILE, 3018f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall false); 3019874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } 302004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(SuperRep); 302104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 30226568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff } 302304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 302404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::Instance: { 302504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Remove all type-casts because it may contain objc-style types; e.g. 302604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Foo<Proto> *. 302704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *recExpr = Exp->getInstanceReceiver(); 302804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) 302904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor recExpr = CE->getSubExpr(); 303004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 3031a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, recExpr); 303204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(recExpr); 303304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 303404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 303504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 303604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 3037beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff // Create a call to sel_registerName("selName"), it will be the 2nd argument. 30385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> SelExprs; 3039934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff QualType argType = Context->getPointerType(Context->CharTy); 30401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SelExprs.push_back(StringLiteral::Create(*Context, 304165aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad Exp->getSelector().getAsString(), 30425cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 30435cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor argType, SourceLocation())); 3044934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 30451d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian &SelExprs[0], SelExprs.size(), 30461d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian StartLoc, 30471d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian EndLoc); 3048934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff MsgExprs.push_back(SelExp); 30491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3050934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Now push any user supplied arguments. 3051934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff for (unsigned i = 0; i < Exp->getNumArgs(); i++) { 30526568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff Expr *userExpr = Exp->getArg(i); 30537e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff // Make all implicit casts explicit...ICE comes in handy:-) 30547e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { 30557e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff // Reuse the ICE type, it is exactly what the doctor ordered. 3056dff3f018e0bf93a08f135954a5771bfe664a7744Fariborz Jahanian QualType type = ICE->getType(); 3057dff3f018e0bf93a08f135954a5771bfe664a7744Fariborz Jahanian if (needToScanForQualifiers(type)) 3058dff3f018e0bf93a08f135954a5771bfe664a7744Fariborz Jahanian type = Context->getObjCIdType(); 30591f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // Make sure we convert "type (^)(...)" to "type (*)(...)". 30604fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(type); 30611a38b46ae2f818592577546c8c800ada8de7962bFariborz Jahanian const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 30621d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CastKind CK; 30631d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall if (SubExpr->getType()->isIntegralType(*Context) && 30641d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall type->isBooleanType()) { 30651d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_IntegralToBoolean; 30661d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else if (type->isObjCObjectPointerType()) { 30671d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall if (SubExpr->getType()->isBlockPointerType()) { 30681d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BlockPointerToObjCPointerCast; 30691d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else if (SubExpr->getType()->isPointerType()) { 30701d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_CPointerToObjCPointerCast; 30711d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else { 30721d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BitCast; 30731d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } 30741d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else { 30751d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BitCast; 30761d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } 30771d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall 30781d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); 3079d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian } 3080d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian // Make id<P...> cast into an 'id' cast. 30816eec8e883de118b431e3ead5b1e604a6ac68ff6bDouglas Gregor else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { 3082a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (CE->getType()->isObjCQualifiedIdType()) { 30836eec8e883de118b431e3ead5b1e604a6ac68ff6bDouglas Gregor while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) 3084d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian userExpr = CE->getSubExpr(); 30851d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CastKind CK; 30861d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall if (userExpr->getType()->isIntegralType(*Context)) { 30871d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_IntegralToPointer; 30881d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else if (userExpr->getType()->isBlockPointerType()) { 30891d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BlockPointerToObjCPointerCast; 30901d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else if (userExpr->getType()->isPointerType()) { 30911d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_CPointerToObjCPointerCast; 30921d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else { 30931d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BitCast; 30941d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } 30959d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 30961d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK, userExpr); 3097d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian } 30981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 30996568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff MsgExprs.push_back(userExpr); 3100621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // We've transferred the ownership to MsgExprs. For now, we *don't* null 3101621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // out the argument in the original expression (since we aren't deleting 3102f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info. 3103621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff //Exp->setArg(i, 0); 3104934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff } 3105ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Generate the funky cast. 3106ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff CastExpr *cast; 31075f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 8> ArgTypes; 3108ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff QualType returnType; 31091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3110ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Push 'id' and 'SEL', the 2 implicit arguments. 3111c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff if (MsgSendFlavor == MsgSendSuperFunctionDecl) 3112c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff ArgTypes.push_back(Context->getPointerType(getSuperStructType())); 3113c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff else 3114a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ArgTypes.push_back(Context->getObjCIdType()); 3115a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ArgTypes.push_back(Context->getObjCSelType()); 311689951a86b594513c2a013532ed45d197413b1087Chris Lattner if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { 3117ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Push any user argument types. 311889951a86b594513c2a013532ed45d197413b1087Chris Lattner for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 311989951a86b594513c2a013532ed45d197413b1087Chris Lattner E = OMD->param_end(); PI != E; ++PI) { 312089951a86b594513c2a013532ed45d197413b1087Chris Lattner QualType t = (*PI)->getType()->isObjCQualifiedIdType() 31211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ? Context->getObjCIdType() 312289951a86b594513c2a013532ed45d197413b1087Chris Lattner : (*PI)->getType(); 3123a206b0614a392cfef19aaaa894f9d3c756006421Steve Naroff // Make sure we convert "t (^)(...)" to "t (*)(...)". 31244fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(t); 3125352336bb0a480b044eb03e7359e73d3b173d9cddSteve Naroff ArgTypes.push_back(t); 3126352336bb0a480b044eb03e7359e73d3b173d9cddSteve Naroff } 312789951a86b594513c2a013532ed45d197413b1087Chris Lattner returnType = OMD->getResultType()->isObjCQualifiedIdType() 312889951a86b594513c2a013532ed45d197413b1087Chris Lattner ? Context->getObjCIdType() : OMD->getResultType(); 31294fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(returnType); 3130ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff } else { 3131a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek returnType = Context->getObjCIdType(); 3132ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff } 3133ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Get the type, we will need to reference it in a couple spots. 3134874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType msgSendType = MsgSendFlavor->getType(); 31351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3136ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Create a reference to the objc_msgSend() declaration. 31371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, 3138f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_LValue, SourceLocation()); 3139ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff 31401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 3141ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // If we don't do this cast, we get the following bizarre warning/note: 3142ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // xx.m:13: warning: function called through a non-compatible type 3143ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // xx.m:13: note: if this code is reached, the program will abort 31449d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast = NoTypeInfoCStyleCastExpr(Context, 31459d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Context->getPointerType(Context->VoidTy), 3146a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, DRE); 31471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3148ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Now do the "normal" pointer to function cast. 3149e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType castType = 3150e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 3151e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall // If we don't have a method decl, force a variadic cast. 3152e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true); 3153ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff castType = Context->getPointerType(castType); 3154a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 31559d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast); 3156ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff 3157ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Don't forget the parens to enforce the proper binding. 31581d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 31591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3160183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *FT = msgSendType->getAs<FunctionType>(); 3161668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 31621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MsgExprs.size(), 3163f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FT->getResultType(), VK_RValue, 3164f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall EndLoc); 316533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian Stmt *ReplacingStmt = CE; 316680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (MsgSendStretFlavor) { 316780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // We have the method which returns a struct/union. Must also generate 316880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // call to objc_msgSend_stret and hang both varieties on a conditional 316980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // expression which dictate which one to envoke depending on size of 317080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // method's return type. 31711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 317280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Create a reference to the objc_msgSend_stret() declaration. 31731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType, 3174f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_LValue, SourceLocation()); 317580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Need to cast objc_msgSend_stret to "void *" (see above comment). 31769d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast = NoTypeInfoCStyleCastExpr(Context, 31779d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Context->getPointerType(Context->VoidTy), 3178a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, STDRE); 317980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Now do the "normal" pointer to function cast. 3180e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 3181e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false); 318280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian castType = Context->getPointerType(castType); 3183a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 31849d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast); 31851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 318680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Don't forget the parens to enforce the proper binding. 31878189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); 31881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3189183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall FT = msgSendType->getAs<FunctionType>(); 3190668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 31911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MsgExprs.size(), 3192f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FT->getResultType(), VK_RValue, 3193f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 31941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 319580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Build sizeof(returnType) 3196f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne UnaryExprOrTypeTraitExpr *sizeofExpr = 3197f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf, 3198f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne Context->getTrivialTypeSourceInfo(returnType), 3199f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne Context->getSizeType(), SourceLocation(), 3200f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne SourceLocation()); 320180a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 320280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. 320380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // For X86 it is more complicated and some kind of target specific routine 320480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // is needed to decide what to do. 32051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump unsigned IntSize = 320698be4943e8dc4f3905629a7102668960873cf863Chris Lattner static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 32079996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis IntegerLiteral *limit = IntegerLiteral::Create(*Context, 32089996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis llvm::APInt(IntSize, 8), 32099996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis Context->IntTy, 32109996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis SourceLocation()); 3211f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall BinaryOperator *lessThanExpr = 3212f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, 3213f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, SourceLocation()); 321480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 32151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConditionalOperator *CondExpr = 321647e1f7c68bf375cac470fdb2b599ddbb395aeb52Douglas Gregor new (Context) ConditionalOperator(lessThanExpr, 321747e1f7c68bf375cac470fdb2b599ddbb395aeb52Douglas Gregor SourceLocation(), CE, 321856ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall SourceLocation(), STCE, 32190943168ac126b8047f30f6bd215fbe7db14d61baJohn McCall returnType, VK_RValue, OK_Ordinary); 3220f9b949fecf339a2c9bd97dd11a272c4878f85ce4Fariborz Jahanian ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 3221f9b949fecf339a2c9bd97dd11a272c4878f85ce4Fariborz Jahanian CondExpr); 322280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian } 3223f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 322433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return ReplacingStmt; 322533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian} 322633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian 3227b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { 32281d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(), 32291d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Exp->getLocEnd()); 32301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3231934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Now do the actual rewrite. 3232dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, ReplacingStmt); 32331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3234f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 323533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return ReplacingStmt; 3236ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff} 3237ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff 3238621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// typedef struct objc_object Protocol; 3239621edce9cd7d4e06979daf911cc306350619f33bSteve NaroffQualType RewriteObjC::getProtocolType() { 3240621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!ProtocolTypeDecl) { 3241a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall TypeSourceInfo *TInfo 3242a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); 3243621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, 3244344577e6b58f42d18dc8118c8903b49a85dc005eAbramo Bagnara SourceLocation(), SourceLocation(), 3245621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff &Context->Idents.get("Protocol"), 3246a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall TInfo); 3247621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3248621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return Context->getTypeDeclType(ProtocolTypeDecl); 3249621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff} 3250621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 325136ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian/// RewriteObjCProtocolExpr - Rewrite a protocol expression into 3252621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// a synthesized/forward data reference (to the protocol's metadata). 3253621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// The forward references (and metadata) are generated in 3254621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// RewriteObjC::HandleTranslationUnit(). 3255b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { 3256621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); 3257621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff IdentifierInfo *ID = &Context->Idents.get(Name); 32581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 3259ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), ID, getProtocolType(), 0, 3260d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, SC_None); 3261f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), VK_LValue, 3262f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 32632de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, 3264621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getPointerType(DRE->getType()), 3265f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, SourceLocation()); 32669d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), 3267a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 32689d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall DerefExpr); 3269621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ReplaceStmt(Exp, castExpr); 3270621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolExprDecls.insert(Exp->getProtocol()); 3271f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 3272621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return castExpr; 32731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 327436ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian} 327536ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian 32761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, 3277baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff const char *endBuf) { 3278baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff while (startBuf < endBuf) { 3279baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (*startBuf == '#') { 3280baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // Skip whitespace. 3281baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf) 3282baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff ; 3283baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (!strncmp(startBuf, "if", strlen("if")) || 3284baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "ifdef", strlen("ifdef")) || 3285baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "ifndef", strlen("ifndef")) || 3286baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "define", strlen("define")) || 3287baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "undef", strlen("undef")) || 3288baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "else", strlen("else")) || 3289baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "elif", strlen("elif")) || 3290baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "endif", strlen("endif")) || 3291baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "pragma", strlen("pragma")) || 3292baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "include", strlen("include")) || 3293baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "import", strlen("import")) || 3294baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "include_next", strlen("include_next"))) 3295baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff return true; 3296baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3297baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff startBuf++; 3298baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3299baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff return false; 3300baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff} 3301baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff 3302a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek/// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to 330326e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian/// an objective-c class with ivars. 3304b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, 330526e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result) { 3306a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); 33074087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar assert(CDecl->getName() != "" && 33082e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor "Name missing in SynthesizeObjCInternalStruct"); 3309212b768a4b39479bc8cce1268a95a1adbd825542Fariborz Jahanian // Do not synthesize more than once. 3310a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (ObjCSynthesizedStructs.count(CDecl)) 3311212b768a4b39479bc8cce1268a95a1adbd825542Fariborz Jahanian return; 3312a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); 3313f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner int NumIvars = CDecl->ivar_size(); 33142c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian SourceLocation LocStart = CDecl->getLocStart(); 33152c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian SourceLocation LocEnd = CDecl->getLocEnd(); 33161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 33172c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 33182c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 33191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3320aff56d0bffdad7ed75db938d5e61e1ce3d5cd195Fariborz Jahanian // If no ivars and no root or if its root, directly or indirectly, 3321f1de0ca05e2df6f23bd559028693a12d1ebdaaf6Fariborz Jahanian // have no ivars (thus not synthesized) then no need to synthesize this class. 3322f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner if ((CDecl->isForwardDecl() || NumIvars == 0) && 3323f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { 33242c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 3325d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, Result); 332626e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian return; 33272c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian } 33281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 33291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME: This has potential of causing problem. If 3330a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek // SynthesizeObjCInternalStruct is ever called recursively. 3331fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result += "\nstruct "; 3332d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 333361ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff if (LangOpts.Microsoft) 333461ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff Result += "_IMPL"; 333505b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff 3336fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian if (NumIvars > 0) { 3337fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff const char *cursor = strchr(startBuf, '{'); 33381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert((cursor && endBuf) 3339a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek && "SynthesizeObjCInternalStruct - malformed @interface"); 3340baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // If the buffer contains preprocessor directives, we do more fine-grained 3341baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrites. This is intended to fix code that looks like (which occurs in 3342baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // NSURL.h, for example): 3343baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // 3344baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #ifdef XYZ 3345baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @interface Foo : NSObject 3346baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #else 3347baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @interface FooBar : NSObject 3348baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #endif 3349baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // { 3350baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // int i; 3351baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // } 3352baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @end 3353baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // 3354baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // This clause is segregated to avoid breaking the common case. 3355baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (BufferContainsPPDirectives(startBuf, cursor)) { 33561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() : 3357baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff CDecl->getClassLoc(); 3358baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff const char *endHeader = SM->getCharacterData(L); 33592c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts); 3360baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff 3361cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl->protocol_begin() != CDecl->protocol_end()) { 3362baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // advance to the end of the referenced protocols. 3363baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff while (endHeader < cursor && *endHeader != '>') endHeader++; 3364baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff endHeader++; 3365baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3366baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrite the original header 3367d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endHeader-startBuf, Result); 3368baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } else { 3369baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrite the original header *without* disturbing the '{' 3370d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, cursor-startBuf, Result); 3371baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3372a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 3373fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result = "\n struct "; 3374d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 337539bbd9f5918950436821585afc6244b1fe2c7295Steve Naroff Result += "_IMPL "; 3376d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 3377819173c41e395744480e8f325dc5c02438420604Steve Naroff Result += "_IVARS;\n"; 33781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3379fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // insert the super class structure definition. 3380f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner SourceLocation OnePastCurly = 3381f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner LocStart.getFileLocWithOffset(cursor-startBuf+1); 3382d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(OnePastCurly, Result); 3383fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff } 3384fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff cursor++; // past '{' 33851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3386fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // Now comment out any visibility specifiers. 3387fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff while (cursor < endBuf) { 3388fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff if (*cursor == '@') { 3389fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); 3390df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner // Skip whitespace. 3391df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor) 3392df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner /*scan*/; 3393df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner 3394fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian // FIXME: presence of @public, etc. inside comment results in 3395fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian // this transformation as well, which is still correct c-code. 3396fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff if (!strncmp(cursor, "public", strlen("public")) || 3397fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff !strncmp(cursor, "private", strlen("private")) || 3398c5e327712499caa2a9f3b6591490de8cb7df0b5bSteve Naroff !strncmp(cursor, "package", strlen("package")) || 33999567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian !strncmp(cursor, "protected", strlen("protected"))) 3400d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, "// "); 3401fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian } 34029567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // FIXME: If there are cases where '<' is used in ivar declaration part 34039567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // of user code, then scan the ivar list and use needToScanForQualifiers 34049567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // for type checking. 34059567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian else if (*cursor == '<') { 34069567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); 3407d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, "/* "); 34089567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian cursor = strchr(cursor, '>'); 34099567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian cursor++; 34109567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); 3411d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, " */"); 3412ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff } else if (*cursor == '^') { // rewrite block specifier. 3413ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff SourceLocation caretLoc = LocStart.getFileLocWithOffset(cursor-startBuf); 3414d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(caretLoc, 1, "*"); 34159567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian } 3416fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff cursor++; 3417fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian } 3418fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // Don't forget to add a ';'!! 3419d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LocEnd.getFileLocWithOffset(1), ";"); 3420fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff } else { // we don't have any instance variables - insert super struct. 34212c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 3422fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result += " {\n struct "; 3423d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 342439bbd9f5918950436821585afc6244b1fe2c7295Steve Naroff Result += "_IMPL "; 3425d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 3426819173c41e395744480e8f325dc5c02438420604Steve Naroff Result += "_IVARS;\n};\n"; 3427d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, Result); 342826e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian } 342926e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian // Mark this struct as having been generated. 3430a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (!ObjCSynthesizedStructs.insert(CDecl)) 3431fbfe82527dadb09c95609a742744d75a2322850cSteve Naroff assert(false && "struct already synthesize- SynthesizeObjCInternalStruct"); 343226e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian} 343326e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian 3434a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or 34352e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian/// class methods. 3436653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregortemplate<typename MethodIterator> 3437653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregorvoid RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 3438653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor MethodIterator MethodEnd, 34398e991ba2e256e56959a65a049e161aa30b3c0decFariborz Jahanian bool IsInstanceMethod, 34405f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef prefix, 34415f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef ClassName, 3442158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner std::string &Result) { 3443ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner if (MethodBegin == MethodEnd) return; 34441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3445ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner if (!objc_impl_method) { 34462e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian /* struct _objc_method { 3447e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian SEL _cmd; 3448e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian char *method_types; 3449e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian void *_imp; 3450e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 34512e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian */ 3452158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "\nstruct _objc_method {\n"; 3453158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "\tSEL _cmd;\n"; 3454158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "\tchar *method_types;\n"; 3455158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "\tvoid *_imp;\n"; 3456158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "};\n"; 34571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3458ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian objc_impl_method = true; 3459ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 34601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3461ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian // Build _objc_method_list for class's methods if needed 34621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3463946a693aea83123f4039012c3bca7bc70800018bSteve Naroff /* struct { 3464946a693aea83123f4039012c3bca7bc70800018bSteve Naroff struct _objc_method_list *next_method; 3465946a693aea83123f4039012c3bca7bc70800018bSteve Naroff int method_count; 3466946a693aea83123f4039012c3bca7bc70800018bSteve Naroff struct _objc_method method_list[]; 3467946a693aea83123f4039012c3bca7bc70800018bSteve Naroff } 3468946a693aea83123f4039012c3bca7bc70800018bSteve Naroff */ 3469653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor unsigned NumMethods = std::distance(MethodBegin, MethodEnd); 3470946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\nstatic struct {\n"; 3471946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tstruct _objc_method_list *next_method;\n"; 3472946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tint method_count;\n"; 3473946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tstruct _objc_method method_list["; 3474653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor Result += utostr(NumMethods); 3475946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "];\n} _OBJC_"; 3476ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += prefix; 3477ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; 3478ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "_METHODS_"; 3479ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += ClassName; 3480dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __"; 3481ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += IsInstanceMethod ? "inst" : "cls"; 3482ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "_meth\")))= "; 3483653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor Result += "{\n\t0, " + utostr(NumMethods) + "\n"; 3484ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner 3485ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "\t,{{(SEL)\""; 3486077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner Result += (*MethodBegin)->getSelector().getAsString().c_str(); 3487ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner std::string MethodTypeString; 3488a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 3489ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "\", \""; 3490ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += MethodTypeString; 3491946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\", (void *)"; 3492ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += MethodInternalNames[*MethodBegin]; 3493ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "}\n"; 3494ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { 3495ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "\t ,{(SEL)\""; 3496077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner Result += (*MethodBegin)->getSelector().getAsString().c_str(); 349733e1d64ab5cd5d27f8530ccd056191fe2c9f3f2eFariborz Jahanian std::string MethodTypeString; 3498a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 349933e1d64ab5cd5d27f8530ccd056191fe2c9f3f2eFariborz Jahanian Result += "\", \""; 350033e1d64ab5cd5d27f8530ccd056191fe2c9f3f2eFariborz Jahanian Result += MethodTypeString; 3501946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\", (void *)"; 3502ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += MethodInternalNames[*MethodBegin]; 3503b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian Result += "}\n"; 3504e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 3505ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "\t }\n};\n"; 35062e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian} 35072e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3508621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. 3509780f329cb011bff0da5763e2e9744eec093d0509Chris Lattnervoid RewriteObjC:: 35105f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerRewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, StringRef prefix, 35115f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef ClassName, std::string &Result) { 3512e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian static bool objc_protocol_methods = false; 3513621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3514621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output struct protocol_methods holder of method selector and type. 3515621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!objc_protocol_methods && !PDecl->isForwardDecl()) { 3516621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff /* struct protocol_methods { 3517621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff SEL _cmd; 3518621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff char *method_types; 3519621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3520621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff */ 3521621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstruct _protocol_methods {\n"; 3522621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct objc_selector *_cmd;\n"; 3523621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tchar *method_types;\n"; 3524621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "};\n"; 35251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3526621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff objc_protocol_methods = true; 3527621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3528621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Do not synthesize the protocol more than once. 3529621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ObjCSynthesizedProtocols.count(PDecl)) 3530621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return; 35311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 353217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 353317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis unsigned NumMethods = std::distance(PDecl->instmeth_begin(), 353417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis PDecl->instmeth_end()); 3535621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff /* struct _objc_protocol_method_list { 3536621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff int protocol_method_count; 3537621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct protocol_methods protocols[]; 3538621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3539621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff */ 3540621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstatic struct {\n"; 3541621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tint protocol_method_count;\n"; 3542621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _protocol_methods protocol_methods["; 3543621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += utostr(NumMethods); 3544621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_"; 3545621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3546621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 3547621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff "{\n\t" + utostr(NumMethods) + "\n"; 35481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3549621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output instance methods declared in this protocol. 35501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCProtocolDecl::instmeth_iterator 35511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 3552621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff I != E; ++I) { 355317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (I == PDecl->instmeth_begin()) 3554621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t ,{{(struct objc_selector *)\""; 3555621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3556621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t ,{(struct objc_selector *)\""; 35574087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar Result += (*I)->getSelector().getAsString(); 3558621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string MethodTypeString; 3559621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); 3560621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\", \""; 3561621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += MethodTypeString; 3562621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\"}\n"; 35639d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 3564621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t }\n};\n"; 3565621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 35661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3567621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output class methods declared in this protocol. 356817945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis unsigned NumMethods = std::distance(PDecl->classmeth_begin(), 356917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis PDecl->classmeth_end()); 3570621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (NumMethods > 0) { 3571621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff /* struct _objc_protocol_method_list { 3572621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff int protocol_method_count; 3573621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct protocol_methods protocols[]; 3574621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 35759d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner */ 3576621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstatic struct {\n"; 3577621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tint protocol_method_count;\n"; 3578621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _protocol_methods protocol_methods["; 3579621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += utostr(NumMethods); 3580621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_"; 3581d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += PDecl->getNameAsString(); 3582621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 3583621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff "{\n\t"; 3584621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += utostr(NumMethods); 3585621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\n"; 35861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3587621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output instance methods declared in this protocol. 35881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCProtocolDecl::classmeth_iterator 358917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 3590621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff I != E; ++I) { 359117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (I == PDecl->classmeth_begin()) 3592621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t ,{{(struct objc_selector *)\""; 3593621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3594621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t ,{(struct objc_selector *)\""; 35954087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar Result += (*I)->getSelector().getAsString(); 3596621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string MethodTypeString; 3597621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); 3598621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\", \""; 3599621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += MethodTypeString; 3600621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\"}\n"; 3601e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 3602621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t }\n};\n"; 3603621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3604621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3605621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output: 3606621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff /* struct _objc_protocol { 3607621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Objective-C 1.0 extensions 3608621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct _objc_protocol_extension *isa; 3609621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff char *protocol_name; 3610621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct _objc_protocol **protocol_list; 3611621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct _objc_protocol_method_list *instance_methods; 3612621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct _objc_protocol_method_list *class_methods; 36131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 3614621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff */ 3615621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff static bool objc_protocol = false; 3616621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!objc_protocol) { 3617621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstruct _objc_protocol {\n"; 3618621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _objc_protocol_extension *isa;\n"; 3619621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tchar *protocol_name;\n"; 3620621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _objc_protocol **protocol_list;\n"; 3621621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _objc_protocol_method_list *instance_methods;\n"; 3622621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _objc_protocol_method_list *class_methods;\n"; 36239d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "};\n"; 36241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3625621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff objc_protocol = true; 3626621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 36271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3628621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_"; 3629621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3630621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 3631621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff "{\n\t0, \""; 3632621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3633621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\", 0, "; 363417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 3635621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; 3636621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3637621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += ", "; 36389d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 3639621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3640621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "0, "; 364117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (PDecl->classmeth_begin() != PDecl->classmeth_end()) { 3642621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; 3643621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3644621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\n"; 3645621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3646621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3647621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "0\n"; 3648621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "};\n"; 36491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3650621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Mark this protocol as having been generated. 3651621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!ObjCSynthesizedProtocols.insert(PDecl)) 3652621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff assert(false && "protocol already synthesized"); 3653621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3654621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff} 3655621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3656621edce9cd7d4e06979daf911cc306350619f33bSteve Naroffvoid RewriteObjC:: 3657621edce9cd7d4e06979daf911cc306350619f33bSteve NaroffRewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, 36585f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef prefix, StringRef ClassName, 3659621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string &Result) { 3660621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (Protocols.empty()) return; 36611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3662621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff for (unsigned i = 0; i != Protocols.size(); i++) 3663621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result); 3664621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 36659d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner // Output the top lovel protocol meta-data for the class. 36669d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner /* struct _objc_protocol_list { 36679d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner struct _objc_protocol_list *next; 36689d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner int protocol_count; 36699d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner struct _objc_protocol *class_protocols[]; 36709d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 36719d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner */ 36729d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\nstatic struct {\n"; 36739d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\tstruct _objc_protocol_list *next;\n"; 36749d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\tint protocol_count;\n"; 36759d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\tstruct _objc_protocol *class_protocols["; 36769d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += utostr(Protocols.size()); 36779d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "];\n} _OBJC_"; 36789d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += prefix; 36799d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "_PROTOCOLS_"; 36809d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += ClassName; 36819d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 36829d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner "{\n\t0, "; 36839d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += utostr(Protocols.size()); 36849d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\n"; 36851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36869d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\t,{&_OBJC_PROTOCOL_"; 3687d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += Protocols[0]->getNameAsString(); 36889d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += " \n"; 36891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36909d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner for (unsigned i = 1; i != Protocols.size(); i++) { 36919d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\t ,&_OBJC_PROTOCOL_"; 3692d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += Protocols[i]->getNameAsString(); 36939d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\n"; 36949d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 36959d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\t }\n};\n"; 36962e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian} 36972e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3698621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 36991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category 37002e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian/// implementation. 3701b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, 3702ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian std::string &Result) { 3703a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 37042e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Find category declaration for this implementation. 3705a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCCategoryDecl *CDecl; 37061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (CDecl = ClassDecl->getCategoryList(); CDecl; 37072e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian CDecl = CDecl->getNextClassCategory()) 37082e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian if (CDecl->getIdentifier() == IDecl->getIdentifier()) 37092e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian break; 37101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3711d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string FullCategoryName = ClassDecl->getNameAsString(); 3712eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner FullCategoryName += '_'; 3713d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner FullCategoryName += IDecl->getNameAsString(); 37141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37152e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Build _objc_method_list for class's instance methods if needed 37165f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ObjCMethodDecl *, 32> 371717945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 3718653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor 3719653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor // If any of our property implementations have associated getters or 3720653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor // setters, produce metadata for them as well. 372117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 372217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis PropEnd = IDecl->propimpl_end(); 3723653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor Prop != PropEnd; ++Prop) { 3724653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 3725653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3726653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (!(*Prop)->getPropertyIvarDecl()) 3727653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3728653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); 3729653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (!PD) 3730653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3731653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 3732653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor InstanceMethods.push_back(Getter); 3733653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (PD->isReadOnly()) 3734653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3735653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 3736653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor InstanceMethods.push_back(Setter); 3737653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor } 3738653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 3739eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner true, "CATEGORY_", FullCategoryName.c_str(), 3740eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner Result); 37411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37422e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Build _objc_method_list for class's class methods if needed 374317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 3744eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner false, "CATEGORY_", FullCategoryName.c_str(), 3745eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner Result); 37461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37472e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Protocols referenced in class declaration? 3748bac97d43c9552ac0e084bb81fb7404908f1e9970Fariborz Jahanian // Null CDecl is case of a category implementation with no category interface 3749bac97d43c9552ac0e084bb81fb7404908f1e9970Fariborz Jahanian if (CDecl) 3750621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", 37514087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FullCategoryName, Result); 37522e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian /* struct _objc_category { 37532e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian char *category_name; 37542e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian char *class_name; 37552e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian struct _objc_method_list *instance_methods; 37562e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian struct _objc_method_list *class_methods; 37572e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian struct _objc_protocol_list *protocols; 37582e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Objective-C 1.0 extensions 37592e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian uint32_t size; // sizeof (struct _objc_category) 37601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump struct _objc_property_list *instance_properties; // category's own 37612e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // @property decl. 37621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 37632e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian */ 37641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37652e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian static bool objc_category = false; 37662e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian if (!objc_category) { 3767ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_category {\n"; 3768ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *category_name;\n"; 3769ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *class_name;\n"; 3770ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_method_list *instance_methods;\n"; 3771ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_method_list *class_methods;\n"; 3772ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_protocol_list *protocols;\n"; 37731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\tunsigned int size;\n"; 3774ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_property_list *instance_properties;\n"; 3775ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 37762e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian objc_category = true; 3777e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 3778ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstatic struct _objc_category _OBJC_CATEGORY_"; 3779ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += FullCategoryName; 3780dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\""; 3781d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += IDecl->getNameAsString(); 3782ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\"\n\t, \""; 3783d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += ClassDecl->getNameAsString(); 3784ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\"\n"; 37851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 378617945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 3787ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, (struct _objc_method_list *)" 3788ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "&_OBJC_CATEGORY_INSTANCE_METHODS_"; 3789ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += FullCategoryName; 3790ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 3791ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 37922e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian else 3793ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, 0\n"; 379417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 3795ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, (struct _objc_method_list *)" 3796ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "&_OBJC_CATEGORY_CLASS_METHODS_"; 3797ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += FullCategoryName; 3798ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 3799ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 38002e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian else 3801ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, 0\n"; 38021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3803cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) { 38041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; 3805ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += FullCategoryName; 3806ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 3807ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 38082e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian else 3809ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, 0\n"; 3810ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, sizeof(struct _objc_category), 0\n};\n"; 38112e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian} 38122e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 381326e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of 381426e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian/// ivar offset. 38152d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanianvoid RewriteObjC::SynthesizeIvarOffsetComputation(ObjCIvarDecl *ivar, 381626e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result) { 38178f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff if (ivar->isBitField()) { 38188f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff // FIXME: The hack below doesn't work for bitfields. For now, we simply 38198f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff // place all bitfields at offset 0. 38208f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += "0"; 38218f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff } else { 38228f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += "__OFFSETOFIVAR__(struct "; 38232d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian Result += ivar->getContainingInterface()->getNameAsString(); 38248f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff if (LangOpts.Microsoft) 38258f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += "_IMPL"; 38268f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += ", "; 3827d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += ivar->getNameAsString(); 38288f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += ")"; 38298f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff } 383026e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian} 383126e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian 38322e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian//===----------------------------------------------------------------------===// 38332e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian// Meta Data Emission 38342e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian//===----------------------------------------------------------------------===// 38352e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3836b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 3837ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian std::string &Result) { 3838a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 38391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3840fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner // Explicitly declared @interface's are already synthesized. 384133feeb019a5742b286eededd5446ec0fe87c5a61Steve Naroff if (CDecl->isImplicitInterfaceDecl()) { 38421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME: Implementation of a class with no @interface (legacy) doese not 3843ebe668fac7553b9932e1936a997e96dc08c9cae4Fariborz Jahanian // produce correct synthesis as yet. 3844a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek SynthesizeObjCInternalStruct(CDecl, Result); 3845ebe668fac7553b9932e1936a997e96dc08c9cae4Fariborz Jahanian } 38461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3847be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner // Build _objc_ivar_list metadata for classes ivars if needed 384817945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis unsigned NumIvars = !IDecl->ivar_empty() 38491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ? IDecl->ivar_size() 3850f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner : (CDecl ? CDecl->ivar_size() : 0); 38512e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian if (NumIvars > 0) { 38522e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian static bool objc_ivar = false; 38532e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian if (!objc_ivar) { 38542e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian /* struct _objc_ivar { 38552e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian char *ivar_name; 38562e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian char *ivar_type; 38572e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian int ivar_offset; 38581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 38592e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian */ 3860ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_ivar {\n"; 3861ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *ivar_name;\n"; 3862ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *ivar_type;\n"; 3863ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tint ivar_offset;\n"; 3864ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 38651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38662e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian objc_ivar = true; 38672e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian } 38682e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3869946a693aea83123f4039012c3bca7bc70800018bSteve Naroff /* struct { 3870946a693aea83123f4039012c3bca7bc70800018bSteve Naroff int ivar_count; 3871946a693aea83123f4039012c3bca7bc70800018bSteve Naroff struct _objc_ivar ivar_list[nIvars]; 38721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 3873946a693aea83123f4039012c3bca7bc70800018bSteve Naroff */ 38741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\nstatic struct {\n"; 3875946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tint ivar_count;\n"; 3876946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tstruct _objc_ivar ivar_list["; 3877946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += utostr(NumIvars); 3878946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "];\n} _OBJC_INSTANCE_VARIABLES_"; 3879d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += IDecl->getNameAsString(); 3880dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 3881ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "{\n\t"; 3882ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += utostr(NumIvars); 3883ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 38841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3885a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl::ivar_iterator IVI, IVE; 38865f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ObjCIvarDecl *, 8> IVars; 388717945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (!IDecl->ivar_empty()) { 388811062e11236b7bc689dad150e8b490fd6b063ec3Fariborz Jahanian for (ObjCInterfaceDecl::ivar_iterator 388917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); 38908f36aba016c2d236a90f9ecf0a66904209202202Douglas Gregor IV != IVEnd; ++IV) 38918f36aba016c2d236a90f9ecf0a66904209202202Douglas Gregor IVars.push_back(*IV); 389211062e11236b7bc689dad150e8b490fd6b063ec3Fariborz Jahanian IVI = IDecl->ivar_begin(); 389311062e11236b7bc689dad150e8b490fd6b063ec3Fariborz Jahanian IVE = IDecl->ivar_end(); 3894be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner } else { 3895be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner IVI = CDecl->ivar_begin(); 3896be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner IVE = CDecl->ivar_end(); 3897be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner } 3898ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t,{{\""; 3899d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += (*IVI)->getNameAsString(); 3900160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += "\", \""; 3901621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string TmpString, StrEncoding; 3902621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); 3903621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QuoteDoublequotes(TmpString, StrEncoding); 3904160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += StrEncoding; 3905160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += "\", "; 39062d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian SynthesizeIvarOffsetComputation(*IVI, Result); 390726e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian Result += "}\n"; 3908be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner for (++IVI; IVI != IVE; ++IVI) { 3909ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t ,{\""; 3910d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += (*IVI)->getNameAsString(); 3911160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += "\", \""; 3912621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string TmpString, StrEncoding; 3913621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); 3914621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QuoteDoublequotes(TmpString, StrEncoding); 3915160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += StrEncoding; 3916160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += "\", "; 39172d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian SynthesizeIvarOffsetComputation((*IVI), Result); 391826e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian Result += "}\n"; 3919ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 39201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3921ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t }\n};\n"; 39222e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian } 39231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39242e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Build _objc_method_list for class's instance methods if needed 39255f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ObjCMethodDecl *, 32> 392617945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 3927653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor 3928653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor // If any of our property implementations have associated getters or 3929653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor // setters, produce metadata for them as well. 393017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 393117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis PropEnd = IDecl->propimpl_end(); 3932653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor Prop != PropEnd; ++Prop) { 3933653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 3934653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3935653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (!(*Prop)->getPropertyIvarDecl()) 3936653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3937653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); 3938653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (!PD) 3939653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3940653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 3941ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (!Getter->isDefined()) 3942ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian InstanceMethods.push_back(Getter); 3943653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (PD->isReadOnly()) 3944653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3945653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 3946ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (!Setter->isDefined()) 3947ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian InstanceMethods.push_back(Setter); 3948653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor } 3949653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 39504087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar true, "", IDecl->getName(), Result); 39511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39522e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Build _objc_method_list for class's class methods if needed 395317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 39544087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar false, "", IDecl->getName(), Result); 39551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39562e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Protocols referenced in class declaration? 3957621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), 39584087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar "CLASS", CDecl->getName(), Result); 39591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3960deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian // Declaration of class/meta-class metadata 3961deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian /* struct _objc_class { 3962deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian struct _objc_class *isa; // or const char *root_class_name when metadata 39639f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian const char *super_class_name; 39649f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian char *name; 39659f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian long version; 39669f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian long info; 39679f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian long instance_size; 3968deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian struct _objc_ivar_list *ivars; 3969deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian struct _objc_method_list *methods; 39709f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian struct objc_cache *cache; 39719f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian struct objc_protocol_list *protocols; 39729f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian const char *ivar_layout; 39739f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian struct _objc_class_ext *ext; 39741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 39759f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian */ 3976deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian static bool objc_class = false; 3977deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian if (!objc_class) { 3978ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_class {\n"; 3979ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_class *isa;\n"; 3980ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tconst char *super_class_name;\n"; 3981ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *name;\n"; 3982ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong version;\n"; 3983ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong info;\n"; 3984ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong instance_size;\n"; 3985ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_ivar_list *ivars;\n"; 3986ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_method_list *methods;\n"; 3987ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct objc_cache *cache;\n"; 3988ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_protocol_list *protocols;\n"; 3989ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tconst char *ivar_layout;\n"; 3990ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_class_ext *ext;\n"; 3991ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 3992deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian objc_class = true; 39939f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian } 39941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39959f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian // Meta-class metadata generation. 3996a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *RootClass = 0; 3997a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); 39989f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian while (SuperClass) { 39999f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian RootClass = SuperClass; 40009f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian SuperClass = SuperClass->getSuperClass(); 40019f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian } 40029f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian SuperClass = CDecl->getSuperClass(); 40031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4004ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; 4005d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4006dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 4007ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "{\n\t(struct _objc_class *)\""; 4008d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString()); 4009ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 4010ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian 4011ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian if (SuperClass) { 4012ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", \""; 4013d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += SuperClass->getNameAsString(); 4014ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\", \""; 4015d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4016ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 4017ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4018ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian else { 4019ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0, \""; 4020d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4021ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 4022ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4023a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. 40249f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian // 'info' field is initialized to CLS_META(2) for metaclass 4025ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0,2, sizeof(struct _objc_class), 0"; 402617945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 402723f4127411d926fc6a1fe9af7c2bf97e653f16ebSteve Naroff Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; 4028d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += IDecl->getNameAsString(); 40291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\n"; 4030ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 40319f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian else 4032ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0\n"; 4033cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl->protocol_begin() != CDecl->protocol_end()) { 40348eb4a5e70a1bc3d832f90a150fdd84096532c2e2Steve Naroff Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; 4035d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4036ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ",0,0\n"; 4037ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4038454cb012a948ab3dfef5e80ee32b470689c42ba5Fariborz Jahanian else 4039ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t,0,0,0,0\n"; 4040ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 40411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4042deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian // class metadata generation. 4043ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstatic struct _objc_class _OBJC_CLASS_"; 4044d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4045dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= " 4046ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "{\n\t&_OBJC_METACLASS_"; 4047d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4048ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian if (SuperClass) { 4049ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", \""; 4050d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += SuperClass->getNameAsString(); 4051ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\", \""; 4052d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4053ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 4054ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4055ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian else { 4056ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0, \""; 4057d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4058ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 4059ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4060deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian // 'info' field is initialized to CLS_CLASS(1) for class 40614d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian Result += ", 0,1"; 4062a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (!ObjCSynthesizedStructs.count(CDecl)) 40634d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian Result += ",0"; 40644d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian else { 40654d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian // class has size. Must synthesize its size. 4066909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian Result += ",sizeof(struct "; 4067d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4068ba9ac4e5b86842216a0a0eef5886d41e0d7fed0eSteve Naroff if (LangOpts.Microsoft) 4069ba9ac4e5b86842216a0a0eef5886d41e0d7fed0eSteve Naroff Result += "_IMPL"; 40704d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian Result += ")"; 40714d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian } 4072ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian if (NumIvars > 0) { 4073c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_"; 4074d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4075ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n\t"; 4076ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4077deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian else 4078ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ",0"; 407917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 4080946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; 4081d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 40821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += ", 0\n\t"; 4083ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4084deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian else 4085ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ",0,0"; 4086cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl->protocol_begin() != CDecl->protocol_end()) { 40878eb4a5e70a1bc3d832f90a150fdd84096532c2e2Steve Naroff Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; 4088d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 4089ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0,0\n"; 4090ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4091deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian else 4092ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ",0,0,0\n"; 4093ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 40949f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian} 4095f4d331dd922f92478ebf30e808c0ca97ce49418bFariborz Jahanian 40967a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian/// RewriteImplementations - This routine rewrites all method implementations 40977a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian/// and emits meta-data. 40987a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian 4099ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroffvoid RewriteObjC::RewriteImplementations() { 4100545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian int ClsDefCount = ClassImplementation.size(); 4101545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian int CatDefCount = CategoryImplementation.size(); 41021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 41037a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian // Rewrite implemented methods 41047a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian for (int i = 0; i < ClsDefCount; i++) 41057a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian RewriteImplementationDecl(ClassImplementation[i]); 41061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 410766d6b294af6f114c718039e3279cfd23040cad7bFariborz Jahanian for (int i = 0; i < CatDefCount; i++) 410866d6b294af6f114c718039e3279cfd23040cad7bFariborz Jahanian RewriteImplementationDecl(CategoryImplementation[i]); 4109ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff} 41101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4111ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroffvoid RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { 4112ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff int ClsDefCount = ClassImplementation.size(); 4113ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff int CatDefCount = CategoryImplementation.size(); 41147c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 41152e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // For each implemented class, write out all its meta data. 4116f4d331dd922f92478ebf30e808c0ca97ce49418bFariborz Jahanian for (int i = 0; i < ClsDefCount; i++) 4117a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCClassMetaData(ClassImplementation[i], Result); 41181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 41192e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // For each implemented category, write out all its meta data. 41202e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian for (int i = 0; i < CatDefCount; i++) 4121a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); 4122621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 4123545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian // Write objc_symtab metadata 4124545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian /* 4125545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian struct _objc_symtab 4126545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian { 4127545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian long sel_ref_cnt; 4128545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian SEL *refs; 4129545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian short cls_def_cnt; 4130545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian short cat_def_cnt; 4131545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian void *defs[cls_def_cnt + cat_def_cnt]; 41321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 4133545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian */ 41341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4135ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_symtab {\n"; 4136ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong sel_ref_cnt;\n"; 4137ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tSEL *refs;\n"; 4138ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tshort cls_def_cnt;\n"; 4139ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tshort cat_def_cnt;\n"; 4140ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n"; 4141ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n\n"; 41421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4143ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "static struct _objc_symtab " 4144dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n"; 41451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\t0, 0, " + utostr(ClsDefCount) 4146ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian + ", " + utostr(CatDefCount) + "\n"; 4147ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian for (int i = 0; i < ClsDefCount; i++) { 4148ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t,&_OBJC_CLASS_"; 4149d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += ClassImplementation[i]->getNameAsString(); 4150ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 4151ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 41521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4153ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian for (int i = 0; i < CatDefCount; i++) { 4154ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t,&_OBJC_CATEGORY_"; 4155d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CategoryImplementation[i]->getClassInterface()->getNameAsString(); 4156ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "_"; 4157d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CategoryImplementation[i]->getNameAsString(); 4158ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 4159ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 41601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4161ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n\n"; 41621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4163545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian // Write objc_module metadata 41641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4165545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian /* 4166545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian struct _objc_module { 4167545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian long version; 4168545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian long size; 4169545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian const char *name; 4170545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian struct _objc_symtab *symtab; 4171545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian } 4172545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian */ 41731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4174ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_module {\n"; 4175ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong version;\n"; 4176ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong size;\n"; 4177ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tconst char *name;\n"; 4178ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_symtab *symtab;\n"; 4179ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n\n"; 4180ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "static struct _objc_module " 4181dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n"; 41821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\t" + utostr(OBJC_ABI_VERSION) + 418326e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n"; 4184ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n\n"; 41854f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff 41864f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff if (LangOpts.Microsoft) { 4187621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ProtocolExprDecls.size()) { 4188621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n"; 4189621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "#pragma data_seg(push, \".objc_protocol$B\")\n"; 41901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 4191621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff E = ProtocolExprDecls.end(); I != E; ++I) { 4192621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_"; 4193621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += (*I)->getNameAsString(); 4194621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += " = &_OBJC_PROTOCOL_"; 4195621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += (*I)->getNameAsString(); 4196621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += ";\n"; 4197621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 4198621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "#pragma data_seg(pop)\n\n"; 4199621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 42004f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n"; 42011919032c9b6e9969e42093ee2e75a4de6abcb2b0Steve Naroff Result += "#pragma data_seg(push, \".objc_module_info$B\")\n"; 42024f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff Result += "static struct _objc_module *_POINTER_OBJC_MODULES = "; 42034f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff Result += "&_OBJC_MODULES;\n"; 42044f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff Result += "#pragma data_seg(pop)\n\n"; 42054f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff } 4206545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian} 4207311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner 4208a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanianvoid RewriteObjC::RewriteByRefString(std::string &ResultStr, 4209a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian const std::string &Name, 42101e8011e2fcddc4a638d210ec2dcd21adcf7b1763Fariborz Jahanian ValueDecl *VD, bool def) { 4211a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian assert(BlockByRefDeclNo.count(VD) && 4212a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian "RewriteByRefString: ByRef decl missing"); 42131e8011e2fcddc4a638d210ec2dcd21adcf7b1763Fariborz Jahanian if (def) 42141e8011e2fcddc4a638d210ec2dcd21adcf7b1763Fariborz Jahanian ResultStr += "struct "; 42151e8011e2fcddc4a638d210ec2dcd21adcf7b1763Fariborz Jahanian ResultStr += "__Block_byref_" + Name + 4216a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian "_" + utostr(BlockByRefDeclNo[VD]) ; 4217a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian} 4218a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian 42196cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanianstatic bool HasLocalVariableExternalStorage(ValueDecl *VD) { 42206cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 42216cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage()); 42226cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return false; 42236cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian} 42246cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 422554055232a5ddb9529726e934301b125cb720a273Steve Naroffstd::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, 42265f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef funcName, 422754055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string Tag) { 422854055232a5ddb9529726e934301b125cb720a273Steve Naroff const FunctionType *AFT = CE->getFunctionType(); 422954055232a5ddb9529726e934301b125cb720a273Steve Naroff QualType RT = AFT->getResultType(); 423054055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string StructRef = "struct " + Tag; 4231fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string S = "static " + RT.getAsString(Context->PrintingPolicy) + " __" + 42324087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar funcName.str() + "_" + "block_func_" + utostr(i); 423354055232a5ddb9529726e934301b125cb720a273Steve Naroff 423454055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockDecl *BD = CE->getBlockDecl(); 42351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 423672564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor if (isa<FunctionNoProtoType>(AFT)) { 42371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // No user-supplied arguments. Still need to pass in a pointer to the 4238df8570d1ff98155b74df2a0544068f40b4fd5195Steve Naroff // block (to reference imported block decl refs). 4239df8570d1ff98155b74df2a0544068f40b4fd5195Steve Naroff S += "(" + StructRef + " *__cself)"; 424054055232a5ddb9529726e934301b125cb720a273Steve Naroff } else if (BD->param_empty()) { 424154055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "(" + StructRef + " *__cself)"; 424254055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 424372564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); 424454055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(FT && "SynthesizeBlockFunc: No function proto"); 424554055232a5ddb9529726e934301b125cb720a273Steve Naroff S += '('; 424654055232a5ddb9529726e934301b125cb720a273Steve Naroff // first add the implicit argument. 424754055232a5ddb9529726e934301b125cb720a273Steve Naroff S += StructRef + " *__cself, "; 424854055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string ParamStr; 424954055232a5ddb9529726e934301b125cb720a273Steve Naroff for (BlockDecl::param_iterator AI = BD->param_begin(), 425054055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BD->param_end(); AI != E; ++AI) { 425154055232a5ddb9529726e934301b125cb720a273Steve Naroff if (AI != BD->param_begin()) S += ", "; 4252d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ParamStr = (*AI)->getNameAsString(); 42531f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType QT = (*AI)->getType(); 42544fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (convertBlockPointerToFunctionPointer(QT)) 42554fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian QT.getAsStringInternal(ParamStr, Context->PrintingPolicy); 42561f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian else 42571f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QT.getAsStringInternal(ParamStr, Context->PrintingPolicy); 425854055232a5ddb9529726e934301b125cb720a273Steve Naroff S += ParamStr; 425954055232a5ddb9529726e934301b125cb720a273Steve Naroff } 426054055232a5ddb9529726e934301b125cb720a273Steve Naroff if (FT->isVariadic()) { 426154055232a5ddb9529726e934301b125cb720a273Steve Naroff if (!BD->param_empty()) S += ", "; 426254055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "..."; 426354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 426454055232a5ddb9529726e934301b125cb720a273Steve Naroff S += ')'; 426554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 426654055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " {\n"; 42671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 426854055232a5ddb9529726e934301b125cb720a273Steve Naroff // Create local declarations to avoid rewriting all closure decl ref exprs. 426954055232a5ddb9529726e934301b125cb720a273Steve Naroff // First, emit a declaration for all "by ref" decls. 42705f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 427154055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByRefDecls.end(); I != E; ++I) { 427254055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " "; 4273d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = (*I)->getNameAsString(); 4274a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian std::string TypeString; 4275a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(TypeString, Name, (*I)); 4276a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian TypeString += " *"; 427752b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian Name = TypeString + Name; 4278d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; 42791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 428054055232a5ddb9529726e934301b125cb720a273Steve Naroff // Next, emit a declaration for all "by copy" declarations. 42815f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 428254055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByCopyDecls.end(); I != E; ++I) { 428354055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " "; 428454055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle nested closure invocation. For example: 428554055232a5ddb9529726e934301b125cb720a273Steve Naroff // 428654055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^myImportedClosure)(void); 428754055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedClosure = ^(void) { setGlobalInt(x + y); }; 42881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // 428954055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^anotherClosure)(void); 429054055232a5ddb9529726e934301b125cb720a273Steve Naroff // anotherClosure = ^(void) { 429154055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedClosure(); // import and invoke the closure 429254055232a5ddb9529726e934301b125cb720a273Steve Naroff // }; 429354055232a5ddb9529726e934301b125cb720a273Steve Naroff // 4294e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian if (isTopLevelBlockPointerType((*I)->getType())) { 4295e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian RewriteBlockPointerTypeVariable(S, (*I)); 4296e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian S += " = ("; 4297e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian RewriteBlockPointerType(S, (*I)->getType()); 4298e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian S += ")"; 4299e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n"; 4300e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 4301e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian else { 4302210c248449788d9ef910c8222267029653f83a2fFariborz Jahanian std::string Name = (*I)->getNameAsString(); 43036cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QualType QT = (*I)->getType(); 43046cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(*I)) 43056cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT = Context->getPointerType(QT); 43066cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT.getAsStringInternal(Name, Context->PrintingPolicy); 4307e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian S += Name + " = __cself->" + 4308e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian (*I)->getNameAsString() + "; // bound by copy\n"; 4309e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 431054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 431154055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string RewrittenStr = RewrittenBlockExprs[CE]; 431254055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *cstr = RewrittenStr.c_str(); 431354055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*cstr++ != '{') ; 431454055232a5ddb9529726e934301b125cb720a273Steve Naroff S += cstr; 431554055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "\n"; 431654055232a5ddb9529726e934301b125cb720a273Steve Naroff return S; 431754055232a5ddb9529726e934301b125cb720a273Steve Naroff} 431854055232a5ddb9529726e934301b125cb720a273Steve Naroff 431954055232a5ddb9529726e934301b125cb720a273Steve Naroffstd::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 43205f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef funcName, 432154055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string Tag) { 432254055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string StructRef = "struct " + Tag; 432354055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string S = "static void __"; 43241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 432554055232a5ddb9529726e934301b125cb720a273Steve Naroff S += funcName; 432654055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "_block_copy_" + utostr(i); 432754055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "(" + StructRef; 432854055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "*dst, " + StructRef; 432954055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "*src) {"; 43301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 433154055232a5ddb9529726e934301b125cb720a273Steve Naroff E = ImportedBlockDecls.end(); I != E; ++I) { 4332a3f61ae2c824d3999d77efb46f2f996f86885d20Fariborz Jahanian ValueDecl *VD = (*I); 43335bc60d0c324a1b3984cd4a32acb587c8f873ab5fSteve Naroff S += "_Block_object_assign((void*)&dst->"; 4334d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner S += (*I)->getNameAsString(); 433547a242208867fa433d05a78bf346bbb37721a507Steve Naroff S += ", (void*)src->"; 4336d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner S += (*I)->getNameAsString(); 4337bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (BlockByRefDeclsPtrSet.count((*I))) 433873e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 4339a3f61ae2c824d3999d77efb46f2f996f86885d20Fariborz Jahanian else if (VD->getType()->isBlockPointerType()) 434006433c673732fce2a04558a04080cd1ce4e67ef6Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 4341a3f61ae2c824d3999d77efb46f2f996f86885d20Fariborz Jahanian else 4342a3f61ae2c824d3999d77efb46f2f996f86885d20Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 434354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4344d25d1b53f098a4dc52469d9956bdd248ea29b38eFariborz Jahanian S += "}\n"; 4345d25d1b53f098a4dc52469d9956bdd248ea29b38eFariborz Jahanian 434654055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "\nstatic void __"; 434754055232a5ddb9529726e934301b125cb720a273Steve Naroff S += funcName; 434854055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "_block_dispose_" + utostr(i); 434954055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "(" + StructRef; 435054055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "*src) {"; 43511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 435254055232a5ddb9529726e934301b125cb720a273Steve Naroff E = ImportedBlockDecls.end(); I != E; ++I) { 4353a3f61ae2c824d3999d77efb46f2f996f86885d20Fariborz Jahanian ValueDecl *VD = (*I); 43545bc60d0c324a1b3984cd4a32acb587c8f873ab5fSteve Naroff S += "_Block_object_dispose((void*)src->"; 4355d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner S += (*I)->getNameAsString(); 4356bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (BlockByRefDeclsPtrSet.count((*I))) 435773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 4358a3f61ae2c824d3999d77efb46f2f996f86885d20Fariborz Jahanian else if (VD->getType()->isBlockPointerType()) 435906433c673732fce2a04558a04080cd1ce4e67ef6Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 4360a3f61ae2c824d3999d77efb46f2f996f86885d20Fariborz Jahanian else 4361a3f61ae2c824d3999d77efb46f2f996f86885d20Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 436254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 43631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S += "}\n"; 436454055232a5ddb9529726e934301b125cb720a273Steve Naroff return S; 436554055232a5ddb9529726e934301b125cb720a273Steve Naroff} 4366ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis 436701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroffstd::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 436801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string Desc) { 4369ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff std::string S = "\nstruct " + Tag; 437054055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string Constructor = " " + Tag; 43711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 437254055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " {\n struct __block_impl impl;\n"; 437301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += " struct " + Desc; 437401aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += "* Desc;\n"; 43751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 437601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += "(void *fp, "; // Invoke function pointer. 437701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += "struct " + Desc; // Descriptor pointer. 437801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += " *desc"; 43791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 438054055232a5ddb9529726e934301b125cb720a273Steve Naroff if (BlockDeclRefs.size()) { 438154055232a5ddb9529726e934301b125cb720a273Steve Naroff // Output all "by copy" declarations. 43825f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 438354055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByCopyDecls.end(); I != E; ++I) { 438454055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " "; 4385d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string FieldName = (*I)->getNameAsString(); 438654055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string ArgName = "_" + FieldName; 438754055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle nested closure invocation. For example: 438854055232a5ddb9529726e934301b125cb720a273Steve Naroff // 438954055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^myImportedBlock)(void); 439054055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 43911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // 439254055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^anotherBlock)(void); 439354055232a5ddb9529726e934301b125cb720a273Steve Naroff // anotherBlock = ^(void) { 439454055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedBlock(); // import and invoke the closure 439554055232a5ddb9529726e934301b125cb720a273Steve Naroff // }; 439654055232a5ddb9529726e934301b125cb720a273Steve Naroff // 439701f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType((*I)->getType())) { 439854055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "struct __block_impl *"; 439954055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", void *" + ArgName; 440054055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 44016cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QualType QT = (*I)->getType(); 44026cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(*I)) 44036cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT = Context->getPointerType(QT); 44046cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT.getAsStringInternal(FieldName, Context->PrintingPolicy); 44056cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT.getAsStringInternal(ArgName, Context->PrintingPolicy); 440654055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", " + ArgName; 440754055232a5ddb9529726e934301b125cb720a273Steve Naroff } 440854055232a5ddb9529726e934301b125cb720a273Steve Naroff S += FieldName + ";\n"; 440954055232a5ddb9529726e934301b125cb720a273Steve Naroff } 441054055232a5ddb9529726e934301b125cb720a273Steve Naroff // Output all "by ref" declarations. 44115f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 441254055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByRefDecls.end(); I != E; ++I) { 441354055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " "; 4414d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string FieldName = (*I)->getNameAsString(); 441554055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string ArgName = "_" + FieldName; 4416651ba520f9e1b38eeadbfc9bd21d0b7e570d69b7Fariborz Jahanian { 4417a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian std::string TypeString; 4418a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(TypeString, FieldName, (*I)); 441952b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian TypeString += " *"; 442052b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian FieldName = TypeString + FieldName; 442152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ArgName = TypeString + ArgName; 442254055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", " + ArgName; 442354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 442454055232a5ddb9529726e934301b125cb720a273Steve Naroff S += FieldName + "; // by ref\n"; 442554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 442654055232a5ddb9529726e934301b125cb720a273Steve Naroff // Finish writing the constructor. 442720432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += ", int flags=0)"; 442854055232a5ddb9529726e934301b125cb720a273Steve Naroff // Initialize all "by copy" arguments. 442920432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian bool firsTime = true; 44305f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 443154055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByCopyDecls.end(); I != E; ++I) { 4432d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = (*I)->getNameAsString(); 443320432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian if (firsTime) { 443420432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += " : "; 443520432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian firsTime = false; 443620432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian } 443720432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian else 443820432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += ", "; 443920432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian if (isTopLevelBlockPointerType((*I)->getType())) 444020432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += Name + "((struct __block_impl *)_" + Name + ")"; 444120432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian else 444220432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += Name + "(_" + Name + ")"; 444354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 444454055232a5ddb9529726e934301b125cb720a273Steve Naroff // Initialize all "by ref" arguments. 44455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 444654055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByRefDecls.end(); I != E; ++I) { 4447d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = (*I)->getNameAsString(); 444820432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian if (firsTime) { 444920432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += " : "; 445020432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian firsTime = false; 445120432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian } 445220432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian else 445320432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += ", "; 4454651ba520f9e1b38eeadbfc9bd21d0b7e570d69b7Fariborz Jahanian Constructor += Name + "(_" + Name + "->__forwarding)"; 445554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 445620432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian 445720432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += " {\n"; 445820432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian if (GlobalVarDecl) 445920432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 446020432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian else 446120432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 446220432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 446320432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian 446420432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian Constructor += " Desc = desc;\n"; 446554055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 446654055232a5ddb9529726e934301b125cb720a273Steve Naroff // Finish writing the constructor. 446754055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", int flags=0) {\n"; 4468621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (GlobalVarDecl) 4469621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 4470621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 4471621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 447201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 447301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += " Desc = desc;\n"; 447454055232a5ddb9529726e934301b125cb720a273Steve Naroff } 447554055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += " "; 447654055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += "}\n"; 447754055232a5ddb9529726e934301b125cb720a273Steve Naroff S += Constructor; 447854055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "};\n"; 447954055232a5ddb9529726e934301b125cb720a273Steve Naroff return S; 448054055232a5ddb9529726e934301b125cb720a273Steve Naroff} 448139ba4aeca296b1c9f04bde7d9d3cbbf129f1abd3Argyrios Kyrtzidis 448201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroffstd::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, 448301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string ImplTag, int i, 44845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef FunName, 448501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff unsigned hasCopy) { 448601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string S = "\nstatic struct " + DescTag; 448701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 448801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += " {\n unsigned long reserved;\n"; 448901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += " unsigned long Block_size;\n"; 449001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff if (hasCopy) { 44914fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += " void (*copy)(struct "; 44924fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += ImplTag; S += "*, struct "; 44934fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += ImplTag; S += "*);\n"; 44944fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian 44954fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += " void (*dispose)(struct "; 44964fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += ImplTag; S += "*);\n"; 449701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff } 449801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += "} "; 449901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 450001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += DescTag + "_DATA = { 0, sizeof(struct "; 450101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += ImplTag + ")"; 450201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff if (hasCopy) { 45034087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar S += ", __" + FunName.str() + "_block_copy_" + utostr(i); 45044087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar S += ", __" + FunName.str() + "_block_dispose_" + utostr(i); 450501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff } 450601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += "};\n"; 450701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff return S; 450801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff} 450901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 451054055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, 45115f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef FunName) { 4512abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian // Insert declaration for the function in which block literal is used. 4513bf07012cf92253380ce427924870288a34230d1bFariborz Jahanian if (CurFunctionDeclToDeclareForBlock && !Blocks.empty()) 4514abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 45158611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian bool RewriteSC = (GlobalVarDecl && 45168611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian !Blocks.empty() && 4517d931b086984257de68868a64a235c2b4b34003fbJohn McCall GlobalVarDecl->getStorageClass() == SC_Static && 45188611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian GlobalVarDecl->getType().getCVRQualifiers()); 45198611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian if (RewriteSC) { 45208611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian std::string SC(" void __"); 45218611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian SC += GlobalVarDecl->getNameAsString(); 45228611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian SC += "() {}"; 45238611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian InsertText(FunLocStart, SC); 45248611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian } 45258611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian 452654055232a5ddb9529726e934301b125cb720a273Steve Naroff // Insert closures that were part of the function. 452772952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian for (unsigned i = 0, count=0; i < Blocks.size(); i++) { 452872952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian CollectBlockDeclRefInfo(Blocks[i]); 45295e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // Need to copy-in the inner copied-in variables not actually used in this 45305e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // block. 453172952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian for (int j = 0; j < InnerDeclRefsCount[i]; j++) { 453272952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockDeclRefExpr *Exp = InnerDeclRefs[count++]; 453372952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian ValueDecl *VD = Exp->getDecl(); 453472952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockDeclRefs.push_back(Exp); 453572952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) { 453672952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByCopyDeclsPtrSet.insert(VD); 453772952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByCopyDecls.push_back(VD); 453872952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 453972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) { 454072952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByRefDeclsPtrSet.insert(VD); 454172952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByRefDecls.push_back(VD); 454272952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 454392c8568856bf24360f0a90a2161b9962263d4994Fariborz Jahanian // imported objects in the inner blocks not used in the outer 454492c8568856bf24360f0a90a2161b9962263d4994Fariborz Jahanian // blocks must be copied/disposed in the outer block as well. 454592c8568856bf24360f0a90a2161b9962263d4994Fariborz Jahanian if (Exp->isByRef() || 454692c8568856bf24360f0a90a2161b9962263d4994Fariborz Jahanian VD->getType()->isObjCObjectPointerType() || 454792c8568856bf24360f0a90a2161b9962263d4994Fariborz Jahanian VD->getType()->isBlockPointerType()) 454892c8568856bf24360f0a90a2161b9962263d4994Fariborz Jahanian ImportedBlockDecls.insert(VD); 454972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 455054055232a5ddb9529726e934301b125cb720a273Steve Naroff 45514087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i); 45524087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i); 45531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 455401aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); 455554055232a5ddb9529726e934301b125cb720a273Steve Naroff 4556d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, CI); 455754055232a5ddb9529726e934301b125cb720a273Steve Naroff 455801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); 45591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4560d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, CF); 456154055232a5ddb9529726e934301b125cb720a273Steve Naroff 456254055232a5ddb9529726e934301b125cb720a273Steve Naroff if (ImportedBlockDecls.size()) { 456301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); 4564d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, HF); 456554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 456601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, 456701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff ImportedBlockDecls.size() > 0); 4568d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, BD); 45691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 457054055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockDeclRefs.clear(); 457154055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockByRefDecls.clear(); 4572bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByRefDeclsPtrSet.clear(); 457354055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockByCopyDecls.clear(); 4574bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByCopyDeclsPtrSet.clear(); 457554055232a5ddb9529726e934301b125cb720a273Steve Naroff ImportedBlockDecls.clear(); 457654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 45778611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian if (RewriteSC) { 457861b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian // Must insert any 'const/volatile/static here. Since it has been 457961b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian // removed as result of rewriting of block literals. 458061b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian std::string SC; 4581d931b086984257de68868a64a235c2b4b34003fbJohn McCall if (GlobalVarDecl->getStorageClass() == SC_Static) 458261b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian SC = "static "; 458361b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian if (GlobalVarDecl->getType().isConstQualified()) 458461b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian SC += "const "; 458561b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian if (GlobalVarDecl->getType().isVolatileQualified()) 458661b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian SC += "volatile "; 45878611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian if (GlobalVarDecl->getType().isRestrictQualified()) 45888611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian SC += "restrict "; 45898611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian InsertText(FunLocStart, SC); 459061b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian } 459161b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian 459254055232a5ddb9529726e934301b125cb720a273Steve Naroff Blocks.clear(); 45935e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerDeclRefsCount.clear(); 45945e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerDeclRefs.clear(); 459554055232a5ddb9529726e934301b125cb720a273Steve Naroff RewrittenBlockExprs.clear(); 459654055232a5ddb9529726e934301b125cb720a273Steve Naroff} 459754055232a5ddb9529726e934301b125cb720a273Steve Naroff 459854055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { 459954055232a5ddb9529726e934301b125cb720a273Steve Naroff SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 46005f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef FuncName = FD->getName(); 46011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 460254055232a5ddb9529726e934301b125cb720a273Steve Naroff SynthesizeBlockLiterals(FunLocStart, FuncName); 460354055232a5ddb9529726e934301b125cb720a273Steve Naroff} 460454055232a5ddb9529726e934301b125cb720a273Steve Naroff 4605e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanianstatic void BuildUniqueMethodName(std::string &Name, 4606e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian ObjCMethodDecl *MD) { 4607e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian ObjCInterfaceDecl *IFace = MD->getClassInterface(); 46084087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar Name = IFace->getName(); 4609e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian Name += "__" + MD->getSelector().getAsString(); 4610e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian // Convert colons to underscores. 4611e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian std::string::size_type loc = 0; 4612e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian while ((loc = Name.find(":", loc)) != std::string::npos) 4613e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian Name.replace(loc, 1, "_"); 4614e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian} 4615e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian 461654055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { 4617ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); 4618ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff //SourceLocation FunLocStart = MD->getLocStart(); 46190e1c99a1a9068020daa7d85fcafb18490ea6a475Fariborz Jahanian SourceLocation FunLocStart = MD->getLocStart(); 4620e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian std::string FuncName; 4621e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian BuildUniqueMethodName(FuncName, MD); 46224087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar SynthesizeBlockLiterals(FunLocStart, FuncName); 462354055232a5ddb9529726e934301b125cb720a273Steve Naroff} 462454055232a5ddb9529726e934301b125cb720a273Steve Naroff 462554055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::GetBlockDeclRefExprs(Stmt *S) { 46267502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 462754055232a5ddb9529726e934301b125cb720a273Steve Naroff if (*CI) { 462854055232a5ddb9529726e934301b125cb720a273Steve Naroff if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) 462954055232a5ddb9529726e934301b125cb720a273Steve Naroff GetBlockDeclRefExprs(CBE->getBody()); 463054055232a5ddb9529726e934301b125cb720a273Steve Naroff else 463154055232a5ddb9529726e934301b125cb720a273Steve Naroff GetBlockDeclRefExprs(*CI); 463254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 463354055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle specific things. 46346cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) { 463554055232a5ddb9529726e934301b125cb720a273Steve Naroff // FIXME: Handle enums. 463654055232a5ddb9529726e934301b125cb720a273Steve Naroff if (!isa<FunctionDecl>(CDRE->getDecl())) 463754055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockDeclRefs.push_back(CDRE); 46386cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 46396cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) 46406cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(DRE->getDecl())) { 46416cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian BlockDeclRefExpr *BDRE = 46426b5a61b6dc400027fd793dcadceeb9da944a37eaJohn McCall new (Context)BlockDeclRefExpr(cast<VarDecl>(DRE->getDecl()), 46436b5a61b6dc400027fd793dcadceeb9da944a37eaJohn McCall DRE->getType(), 4644f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_LValue, DRE->getLocation(), false); 46456cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian BlockDeclRefs.push_back(BDRE); 46466cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 46476cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 464854055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 464954055232a5ddb9529726e934301b125cb720a273Steve Naroff} 465054055232a5ddb9529726e934301b125cb720a273Steve Naroff 46515e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanianvoid RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, 46525f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs, 465372952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) { 46547502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 46555e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian if (*CI) { 465672952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) { 465772952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl())); 46585e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian GetInnerBlockDeclRefExprs(CBE->getBody(), 46595e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerBlockDeclRefs, 466072952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerContexts); 466172952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 46625e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian else 46635e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian GetInnerBlockDeclRefExprs(*CI, 46645e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerBlockDeclRefs, 466572952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerContexts); 46665e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 46675e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian } 46685e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // Handle specific things. 46696cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) { 46705e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian if (!isa<FunctionDecl>(CDRE->getDecl()) && 467172952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian !InnerContexts.count(CDRE->getDecl()->getDeclContext())) 46725e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerBlockDeclRefs.push_back(CDRE); 46736cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 46746cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 46756cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) 46766cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (Var->isFunctionOrMethodVarDecl()) 46776cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ImportedLocalExternalDecls.insert(Var); 46786cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 467972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian 46805e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian return; 46815e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian} 46825e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 46831f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian/// convertFunctionTypeOfBlocks - This routine converts a function type 46841f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian/// whose result type may be a block pointer or whose argument type(s) 4685fc8f0e14ad142ed811e90fbd9a30e419e301c717Chris Lattner/// might be block pointers to an equivalent function type replacing 46861f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian/// all block pointers to function pointers. 46871f90622e9d24064164df1608ea125d0ed451ac68Fariborz JahanianQualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { 46881f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 46891f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // FTP will be null for closures that don't take arguments. 46901f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // Generate a funky cast. 46915f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 8> ArgTypes; 46921f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType Res = FT->getResultType(); 46934fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian bool HasBlockType = convertBlockPointerToFunctionPointer(Res); 46941f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian 46951f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian if (FTP) { 46961f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 46971f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian E = FTP->arg_type_end(); I && (I != E); ++I) { 46981f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType t = *I; 46991f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // Make sure we convert "t (^)(...)" to "t (*)(...)". 47004fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (convertBlockPointerToFunctionPointer(t)) 47011f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian HasBlockType = true; 47021f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian ArgTypes.push_back(t); 47031f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian } 47041f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian } 47051f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType FuncType; 47061f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // FIXME. Does this work if block takes no argument but has a return type 47071f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // which is of block type? 47081f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian if (HasBlockType) 4709e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size()); 47101f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian else FuncType = QualType(FT, 0); 47111f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian return FuncType; 47121f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian} 47131f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian 47148a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz JahanianStmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 471554055232a5ddb9529726e934301b125cb720a273Steve Naroff // Navigate to relevant type information. 471654055232a5ddb9529726e934301b125cb720a273Steve Naroff const BlockPointerType *CPT = 0; 47171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47188a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { 47196217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek CPT = DRE->getType()->getAs<BlockPointerType>(); 47208a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian } else if (const BlockDeclRefExpr *CDRE = 47218a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian dyn_cast<BlockDeclRefExpr>(BlockExp)) { 47226217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek CPT = CDRE->getType()->getAs<BlockPointerType>(); 47238a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { 47246217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek CPT = MExpr->getType()->getAs<BlockPointerType>(); 47258a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian } 47268a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) { 47278a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian return SynthesizeBlockCall(Exp, PRE->getSubExpr()); 47288a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian } 47298a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 47308a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian CPT = IEXPR->getType()->getAs<BlockPointerType>(); 47318a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian else if (const ConditionalOperator *CEXPR = 47328a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian dyn_cast<ConditionalOperator>(BlockExp)) { 47338a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Expr *LHSExp = CEXPR->getLHS(); 47348a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp); 47358a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Expr *RHSExp = CEXPR->getRHS(); 47368a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); 47378a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Expr *CONDExp = CEXPR->getCond(); 47388a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian ConditionalOperator *CondExpr = 47398a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian new (Context) ConditionalOperator(CONDExp, 47408a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian SourceLocation(), cast<Expr>(LHSStmt), 4741f9b949fecf339a2c9bd97dd11a272c4878f85ce4Fariborz Jahanian SourceLocation(), cast<Expr>(RHSStmt), 47420943168ac126b8047f30f6bd215fbe7db14d61baJohn McCall Exp->getType(), VK_RValue, OK_Ordinary); 47438a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian return CondExpr; 4744e24b22bb58e38253da0bda26da51da7663ca743bFariborz Jahanian } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { 4745e24b22bb58e38253da0bda26da51da7663ca743bFariborz Jahanian CPT = IRE->getType()->getAs<BlockPointerType>(); 474654055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 474754055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(1 && "RewriteBlockClass: Bad type"); 474854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 474954055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(CPT && "RewriteBlockClass: Bad type"); 4750183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); 475154055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(FT && "RewriteBlockClass: Bad type"); 475272564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 475354055232a5ddb9529726e934301b125cb720a273Steve Naroff // FTP will be null for closures that don't take arguments. 47541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4755465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 4756ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 4757aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff &Context->Idents.get("__block_impl")); 4758aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); 475954055232a5ddb9529726e934301b125cb720a273Steve Naroff 4760aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Generate a funky cast. 47615f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 8> ArgTypes; 47621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4763aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Push the block argument type. 4764aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff ArgTypes.push_back(PtrBlock); 476554055232a5ddb9529726e934301b125cb720a273Steve Naroff if (FTP) { 47661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 4767aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff E = FTP->arg_type_end(); I && (I != E); ++I) { 4768aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff QualType t = *I; 4769aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Make sure we convert "t (^)(...)" to "t (*)(...)". 47708188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian if (!convertBlockPointerToFunctionPointer(t)) 47718188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian convertToUnqualifiedObjCType(t); 4772aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff ArgTypes.push_back(t); 4773aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff } 4774aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff } 4775aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Now do the pointer to function cast. 4776e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType PtrToFuncCastType 4777e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size()); 47781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4779aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); 47801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47819d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock, 4782a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 47839d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall const_cast<Expr*>(BlockExp)); 4784aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Don't forget the parens to enforce the proper binding. 47858189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 47868189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek BlkCast); 4787aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff //PE->dump(); 47881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 478944b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 4790ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 4791ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara &Context->Idents.get("FuncPtr"), 4792ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara Context->VoidPtrTy, 0, 47937a614d8380297fcd2bc23986241905d97222948cRichard Smith /*BitWidth=*/0, /*Mutable=*/true, 47947a614d8380297fcd2bc23986241905d97222948cRichard Smith /*HasInit=*/false); 47958189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 4796f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FD->getType(), VK_LValue, 4797f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall OK_Ordinary); 47981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 47998188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian 48009d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, 4801a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, ME); 48028189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); 48031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 48045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> BlkExprs; 4805aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Add the implicit argument. 4806aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff BlkExprs.push_back(BlkCast); 4807aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Add the user arguments. 48081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (CallExpr::arg_iterator I = Exp->arg_begin(), 480954055232a5ddb9529726e934301b125cb720a273Steve Naroff E = Exp->arg_end(); I != E; ++I) { 4810aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff BlkExprs.push_back(*I); 481154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4812668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0], 4813668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek BlkExprs.size(), 4814f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Exp->getType(), VK_RValue, 4815f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 4816aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff return CE; 481754055232a5ddb9529726e934301b125cb720a273Steve Naroff} 481854055232a5ddb9529726e934301b125cb720a273Steve Naroff 4819621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// We need to return the rewritten expression to handle cases where the 4820621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// BlockDeclRefExpr is embedded in another expression being rewritten. 4821621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// For example: 4822621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// 4823621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// int main() { 4824621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// __block Foo *f; 4825621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// __block int i; 48261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// 4827621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// void (^myblock)() = ^() { 4828621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten). 4829621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// i = 77; 4830621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// }; 4831621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff//} 4832f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz JahanianStmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) { 4833bbf37e232b10793b9ec91f4ea01ec168123d5026Fariborz Jahanian // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 4834f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian // for each DeclRefExp where BYREFVAR is name of the variable. 4835f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ValueDecl *VD; 4836f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian bool isArrow = true; 4837f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp)) 4838f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian VD = BDRE->getDecl(); 4839f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian else { 4840f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian VD = cast<DeclRefExpr>(DeclRefExp)->getDecl(); 4841f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian isArrow = false; 4842f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian } 4843f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian 4844ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 4845ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 4846ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian &Context->Idents.get("__forwarding"), 4847ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian Context->VoidPtrTy, 0, 48487a614d8380297fcd2bc23986241905d97222948cRichard Smith /*BitWidth=*/0, /*Mutable=*/true, 48497a614d8380297fcd2bc23986241905d97222948cRichard Smith /*HasInit=*/false); 4850f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow, 4851f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian FD, SourceLocation(), 4852f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FD->getType(), VK_LValue, 4853f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall OK_Ordinary); 4854f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian 48555f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Name = VD->getName(); 4856ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 4857ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian &Context->Idents.get(Name), 4858ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian Context->VoidPtrTy, 0, 48597a614d8380297fcd2bc23986241905d97222948cRichard Smith /*BitWidth=*/0, /*Mutable=*/true, 48607a614d8380297fcd2bc23986241905d97222948cRichard Smith /*HasInit=*/false); 4861ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(), 4862f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExp->getType(), VK_LValue, OK_Ordinary); 4863ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian 4864ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian 4865ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian 4866df8570d1ff98155b74df2a0544068f40b4fd5195Steve Naroff // Need parens to enforce precedence. 4867380ee502b1d91615a753dc490e1e8f83306500b6Fariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 4868380ee502b1d91615a753dc490e1e8f83306500b6Fariborz Jahanian DeclRefExp->getExprLoc(), 4869ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian ME); 4870f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ReplaceStmt(DeclRefExp, PE); 4871621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return PE; 487254055232a5ddb9529726e934301b125cb720a273Steve Naroff} 487354055232a5ddb9529726e934301b125cb720a273Steve Naroff 48746cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian// Rewrites the imported local variable V with external storage 48756cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian// (static, extern, etc.) as *V 48766cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian// 48776cb6eb4c792b504ad652d9230640656852e18ee9Fariborz JahanianStmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { 48786cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ValueDecl *VD = DRE->getDecl(); 48796cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 48806cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (!ImportedLocalExternalDecls.count(Var)) 48816cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return DRE; 4882f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), 4883f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_LValue, OK_Ordinary, 4884f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DRE->getLocation()); 48856cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian // Need parens to enforce precedence. 48866cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 48876cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian Exp); 48886cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ReplaceStmt(DRE, PE); 48896cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return PE; 48906cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian} 48916cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 4892b2f9e516327310d95840d442416084508f80c183Steve Naroffvoid RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { 4893b2f9e516327310d95840d442416084508f80c183Steve Naroff SourceLocation LocStart = CE->getLParenLoc(); 4894b2f9e516327310d95840d442416084508f80c183Steve Naroff SourceLocation LocEnd = CE->getRParenLoc(); 4895fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 4896fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Need to avoid trying to rewrite synthesized casts. 4897fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (LocStart.isInvalid()) 4898fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 48998f6ce5796fb74daf0c4cd39fbda9f7ceb1c7a7b6Steve Naroff // Need to avoid trying to rewrite casts contained in macros. 49008f6ce5796fb74daf0c4cd39fbda9f7ceb1c7a7b6Steve Naroff if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) 49018f6ce5796fb74daf0c4cd39fbda9f7ceb1c7a7b6Steve Naroff return; 49021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 490354055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *startBuf = SM->getCharacterData(LocStart); 490454055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *endBuf = SM->getCharacterData(LocEnd); 49051d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian QualType QT = CE->getType(); 49061d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian const Type* TypePtr = QT->getAs<Type>(); 49071d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian if (isa<TypeOfExprType>(TypePtr)) { 49081d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 49091d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 49101d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian std::string TypeAsString = "("; 4911afad76f6134e635c3cb240ec725d3b7989e7a625Fariborz Jahanian RewriteBlockPointerType(TypeAsString, QT); 49121d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian TypeAsString += ")"; 4913d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); 49141d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian return; 49151d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian } 491654055232a5ddb9529726e934301b125cb720a273Steve Naroff // advance the location to startArgList. 491754055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *argPtr = startBuf; 49181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 491954055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*argPtr++ && (argPtr < endBuf)) { 492054055232a5ddb9529726e934301b125cb720a273Steve Naroff switch (*argPtr) { 4921b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case '^': 4922b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Replace the '^' with '*'. 4923b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf); 4924d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 1, "*"); 4925b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 492654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 492754055232a5ddb9529726e934301b125cb720a273Steve Naroff } 492854055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 492954055232a5ddb9529726e934301b125cb720a273Steve Naroff} 493054055232a5ddb9529726e934301b125cb720a273Steve Naroff 493154055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { 493254055232a5ddb9529726e934301b125cb720a273Steve Naroff SourceLocation DeclLoc = FD->getLocation(); 493354055232a5ddb9529726e934301b125cb720a273Steve Naroff unsigned parenCount = 0; 49341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 493554055232a5ddb9529726e934301b125cb720a273Steve Naroff // We have 1 or more arguments that have closure pointers. 493654055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *startBuf = SM->getCharacterData(DeclLoc); 493754055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *startArgList = strchr(startBuf, '('); 49381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 493954055232a5ddb9529726e934301b125cb720a273Steve Naroff assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); 49401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 494154055232a5ddb9529726e934301b125cb720a273Steve Naroff parenCount++; 494254055232a5ddb9529726e934301b125cb720a273Steve Naroff // advance the location to startArgList. 494354055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf); 494454055232a5ddb9529726e934301b125cb720a273Steve Naroff assert((DeclLoc.isValid()) && "Invalid DeclLoc"); 49451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 494654055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *argPtr = startArgList; 49471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 494854055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*argPtr++ && parenCount) { 494954055232a5ddb9529726e934301b125cb720a273Steve Naroff switch (*argPtr) { 4950b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case '^': 4951b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Replace the '^' with '*'. 4952b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList); 4953d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, 1, "*"); 4954b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 4955b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case '(': 4956b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump parenCount++; 4957b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 4958b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case ')': 4959b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump parenCount--; 4960b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 496154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 496254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 496354055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 496454055232a5ddb9529726e934301b125cb720a273Steve Naroff} 496554055232a5ddb9529726e934301b125cb720a273Steve Naroff 496654055232a5ddb9529726e934301b125cb720a273Steve Naroffbool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { 496772564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *FTP; 49686217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek const PointerType *PT = QT->getAs<PointerType>(); 496954055232a5ddb9529726e934301b125cb720a273Steve Naroff if (PT) { 4970183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 497154055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 49726217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 497354055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 4974183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 497554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 497654055232a5ddb9529726e934301b125cb720a273Steve Naroff if (FTP) { 49771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 497854055232a5ddb9529726e934301b125cb720a273Steve Naroff E = FTP->arg_type_end(); I != E; ++I) 497901f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(*I)) 498054055232a5ddb9529726e934301b125cb720a273Steve Naroff return true; 498154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 498254055232a5ddb9529726e934301b125cb720a273Steve Naroff return false; 498354055232a5ddb9529726e934301b125cb720a273Steve Naroff} 498454055232a5ddb9529726e934301b125cb720a273Steve Naroff 4985e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanianbool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) { 4986e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian const FunctionProtoType *FTP; 4987e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian const PointerType *PT = QT->getAs<PointerType>(); 4988e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian if (PT) { 4989e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 4990e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian } else { 4991e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 4992e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 4993e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 4994e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian } 4995e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian if (FTP) { 4996e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 499706de2cfe0b46e525ba8618536b12aecfbd12d127Fariborz Jahanian E = FTP->arg_type_end(); I != E; ++I) { 499806de2cfe0b46e525ba8618536b12aecfbd12d127Fariborz Jahanian if ((*I)->isObjCQualifiedIdType()) 499906de2cfe0b46e525ba8618536b12aecfbd12d127Fariborz Jahanian return true; 500006de2cfe0b46e525ba8618536b12aecfbd12d127Fariborz Jahanian if ((*I)->isObjCObjectPointerType() && 500106de2cfe0b46e525ba8618536b12aecfbd12d127Fariborz Jahanian (*I)->getPointeeType()->isObjCQualifiedInterfaceType()) 5002e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian return true; 500306de2cfe0b46e525ba8618536b12aecfbd12d127Fariborz Jahanian } 500406de2cfe0b46e525ba8618536b12aecfbd12d127Fariborz Jahanian 5005e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian } 5006e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian return false; 5007e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian} 5008e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian 50098189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenekvoid RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen, 50108189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek const char *&RParen) { 501154055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *argPtr = strchr(Name, '('); 501254055232a5ddb9529726e934301b125cb720a273Steve Naroff assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); 50131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 501454055232a5ddb9529726e934301b125cb720a273Steve Naroff LParen = argPtr; // output the start. 501554055232a5ddb9529726e934301b125cb720a273Steve Naroff argPtr++; // skip past the left paren. 501654055232a5ddb9529726e934301b125cb720a273Steve Naroff unsigned parenCount = 1; 50171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 501854055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*argPtr && parenCount) { 501954055232a5ddb9529726e934301b125cb720a273Steve Naroff switch (*argPtr) { 5020b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case '(': parenCount++; break; 5021b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case ')': parenCount--; break; 5022b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump default: break; 502354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 502454055232a5ddb9529726e934301b125cb720a273Steve Naroff if (parenCount) argPtr++; 502554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 502654055232a5ddb9529726e934301b125cb720a273Steve Naroff assert((*argPtr == ')') && "Rewriter fuzzy parser confused"); 502754055232a5ddb9529726e934301b125cb720a273Steve Naroff RParen = argPtr; // output the end 502854055232a5ddb9529726e934301b125cb720a273Steve Naroff} 502954055232a5ddb9529726e934301b125cb720a273Steve Naroff 503054055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { 503154055232a5ddb9529726e934301b125cb720a273Steve Naroff if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 503254055232a5ddb9529726e934301b125cb720a273Steve Naroff RewriteBlockPointerFunctionArgs(FD); 503354055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 50341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 503554055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle Variables and Typedefs. 503654055232a5ddb9529726e934301b125cb720a273Steve Naroff SourceLocation DeclLoc = ND->getLocation(); 503754055232a5ddb9529726e934301b125cb720a273Steve Naroff QualType DeclT; 503854055232a5ddb9529726e934301b125cb720a273Steve Naroff if (VarDecl *VD = dyn_cast<VarDecl>(ND)) 503954055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclT = VD->getType(); 5040162e1c1b487352434552147967c3dd296ebee2f7Richard Smith else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND)) 504154055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclT = TDD->getUnderlyingType(); 504254055232a5ddb9529726e934301b125cb720a273Steve Naroff else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) 504354055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclT = FD->getType(); 50441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 504554055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled"); 50461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 504754055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *startBuf = SM->getCharacterData(DeclLoc); 504854055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *endBuf = startBuf; 504954055232a5ddb9529726e934301b125cb720a273Steve Naroff // scan backward (from the decl location) for the end of the previous decl. 505054055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) 505154055232a5ddb9529726e934301b125cb720a273Steve Naroff startBuf--; 5052e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian SourceLocation Start = DeclLoc.getFileLocWithOffset(startBuf-endBuf); 5053e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian std::string buf; 5054e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian unsigned OrigLength=0; 505554055232a5ddb9529726e934301b125cb720a273Steve Naroff // *startBuf != '^' if we are dealing with a pointer to function that 505654055232a5ddb9529726e934301b125cb720a273Steve Naroff // may take block argument types (which will be handled below). 505754055232a5ddb9529726e934301b125cb720a273Steve Naroff if (*startBuf == '^') { 505854055232a5ddb9529726e934301b125cb720a273Steve Naroff // Replace the '^' with '*', computing a negative offset. 5059e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf = '*'; 5060e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian startBuf++; 5061e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian OrigLength++; 506254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 5063e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian while (*startBuf != ')') { 5064e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += *startBuf; 5065e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian startBuf++; 5066e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian OrigLength++; 5067e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian } 5068e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += ')'; 5069e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian OrigLength++; 5070e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian 5071e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian if (PointerTypeTakesAnyBlockArguments(DeclT) || 5072e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian PointerTypeTakesAnyObjCQualifiedType(DeclT)) { 507354055232a5ddb9529726e934301b125cb720a273Steve Naroff // Replace the '^' with '*' for arguments. 5074e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian // Replace id<P> with id/*<>*/ 507554055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclLoc = ND->getLocation(); 507654055232a5ddb9529726e934301b125cb720a273Steve Naroff startBuf = SM->getCharacterData(DeclLoc); 507754055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *argListBegin, *argListEnd; 507854055232a5ddb9529726e934301b125cb720a273Steve Naroff GetExtentOfArgList(startBuf, argListBegin, argListEnd); 507954055232a5ddb9529726e934301b125cb720a273Steve Naroff while (argListBegin < argListEnd) { 5080e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian if (*argListBegin == '^') 5081e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += '*'; 5082e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian else if (*argListBegin == '<') { 5083e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += "/*"; 5084e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += *argListBegin++; 5085e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian OrigLength++;; 5086e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian while (*argListBegin != '>') { 5087e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += *argListBegin++; 5088e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian OrigLength++; 5089e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian } 5090e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += *argListBegin; 5091e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += "*/"; 509254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 5093e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian else 5094e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += *argListBegin; 509554055232a5ddb9529726e934301b125cb720a273Steve Naroff argListBegin++; 5096e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian OrigLength++; 509754055232a5ddb9529726e934301b125cb720a273Steve Naroff } 5098e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian buf += ')'; 5099e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian OrigLength++; 510054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 5101e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian ReplaceText(Start, OrigLength, buf); 5102e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian 510354055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 510454055232a5ddb9529726e934301b125cb720a273Steve Naroff} 510554055232a5ddb9529726e934301b125cb720a273Steve Naroff 5106d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 5107d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: 5108d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, 5109d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// struct Block_byref_id_object *src) { 5110d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// _Block_object_assign (&_dest->object, _src->object, 5111d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 5112d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // object 5113d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// _Block_object_assign(&_dest->object, _src->object, 5114d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 5115d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // block 5116d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// } 5117d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// And: 5118d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { 5119d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// _Block_object_dispose(_src->object, 5120d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 5121d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // object 5122d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// _Block_object_dispose(_src->object, 5123d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 5124d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // block 5125d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// } 5126d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 5127ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanianstd::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, 5128ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian int flag) { 5129d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian std::string S; 51301211a71912f263f6991eebfc27a8421a8800b9ecBenjamin Kramer if (CopyDestroyCache.count(flag)) 5131d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian return S; 5132ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian CopyDestroyCache.insert(flag); 5133ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S = "static void __Block_byref_id_object_copy_"; 5134ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += utostr(flag); 5135ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += "(void *dst, void *src) {\n"; 5136ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian 5137d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian // offset into the object pointer is computed as: 5138d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian // void * + void* + int + int + void* + void * 5139d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian unsigned IntSize = 5140d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 5141d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian unsigned VoidPtrSize = 5142d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); 5143d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 51440c4e5d6c499e926a99812a92937df587f67e8362Ken Dyck unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth(); 5145d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += " _Block_object_assign((char*)dst + "; 5146d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(offset); 5147d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += ", *(void * *) ((char*)src + "; 5148d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(offset); 5149d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += "), "; 5150d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(flag); 5151d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += ");\n}\n"; 5152d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 5153ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += "static void __Block_byref_id_object_dispose_"; 5154ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += utostr(flag); 5155ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += "(void *src) {\n"; 5156d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += " _Block_object_dispose(*(void * *) ((char*)src + "; 5157d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(offset); 5158d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += "), "; 5159d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(flag); 5160d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += ");\n}\n"; 5161d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian return S; 5162d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian} 5163d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 516452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// RewriteByRefVar - For each __block typex ND variable this routine transforms 516552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// the declaration into: 516652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// struct __Block_byref_ND { 516752b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// void *__isa; // NULL for everything except __weak pointers 516852b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// struct __Block_byref_ND *__forwarding; 516952b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// int32_t __flags; 517052b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// int32_t __size; 5171d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object 5172d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object 517352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// typex ND; 517452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// }; 517552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// 517652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// It then replaces declaration of ND variable with: 517752b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 517852b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// __size=sizeof(struct __Block_byref_ND), 517952b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// ND=initializer-if-any}; 518052b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// 518152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// 518252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanianvoid RewriteObjC::RewriteByRefVar(VarDecl *ND) { 5183abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian // Insert declaration for the function in which block literal is 5184abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian // used. 5185abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian if (CurFunctionDeclToDeclareForBlock) 5186abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 51872086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian int flag = 0; 51882086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian int isa = 0; 518952b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 5190d64a4f4798907495091daf2b081c3d62d729dca9Fariborz Jahanian if (DeclLoc.isInvalid()) 5191d64a4f4798907495091daf2b081c3d62d729dca9Fariborz Jahanian // If type location is missing, it is because of missing type (a warning). 5192d64a4f4798907495091daf2b081c3d62d729dca9Fariborz Jahanian // Use variable's location which is good for this case. 5193d64a4f4798907495091daf2b081c3d62d729dca9Fariborz Jahanian DeclLoc = ND->getLocation(); 519452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian const char *startBuf = SM->getCharacterData(DeclLoc); 51956f0a0a9d2068c2ee9f399c72bf550c307bb76f9aFariborz Jahanian SourceLocation X = ND->getLocEnd(); 5196402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth X = SM->getExpansionLoc(X); 51976f0a0a9d2068c2ee9f399c72bf550c307bb76f9aFariborz Jahanian const char *endBuf = SM->getCharacterData(X); 519852b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian std::string Name(ND->getNameAsString()); 5199a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian std::string ByrefType; 52001e8011e2fcddc4a638d210ec2dcd21adcf7b1763Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND, true); 520152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " {\n"; 520252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " void *__isa;\n"; 5203a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 5204a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += " *__forwarding;\n"; 520552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " int __flags;\n"; 520652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " int __size;\n"; 5207d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian // Add void *__Block_byref_id_object_copy; 5208d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian // void *__Block_byref_id_object_dispose; if needed. 5209f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian QualType Ty = ND->getType(); 5210f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty); 5211f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian if (HasCopyAndDispose) { 5212d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; 5213d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; 5214f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian } 5215822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian 5216822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian QualType T = Ty; 5217822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian (void)convertBlockPointerToFunctionPointer(T); 5218822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian T.getAsStringInternal(Name, Context->PrintingPolicy); 5219822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian 522052b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " " + Name + ";\n"; 522152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += "};\n"; 522252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian // Insert this type in global scope. It is needed by helper function. 5223dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian SourceLocation FunLocStart; 5224dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian if (CurFunctionDef) 5225dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian FunLocStart = CurFunctionDef->getTypeSpecStartLoc(); 5226dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian else { 5227dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); 5228dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian FunLocStart = CurMethodDef->getLocStart(); 5229dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian } 5230d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, ByrefType); 52312086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian if (Ty.isObjCGCWeak()) { 52322086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian flag |= BLOCK_FIELD_IS_WEAK; 52332086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian isa = 1; 52342086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian } 52352086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian 5236d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian if (HasCopyAndDispose) { 5237ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian flag = BLOCK_BYREF_CALLER; 5238ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian QualType Ty = ND->getType(); 5239ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. 5240ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian if (Ty->isBlockPointerType()) 5241ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian flag |= BLOCK_FIELD_IS_BLOCK; 5242ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian else 5243ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian flag |= BLOCK_FIELD_IS_OBJECT; 5244ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); 5245d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian if (!HF.empty()) 5246d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, HF); 5247d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 524852b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian 524952b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian // struct __Block_byref_ND ND = 525052b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 525152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian // initializer-if-any}; 525252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian bool hasInit = (ND->getInit() != 0); 5253e1f84f8e4cd02347ab0e74eb8f328b3bcacb369cFariborz Jahanian unsigned flags = 0; 5254e1f84f8e4cd02347ab0e74eb8f328b3bcacb369cFariborz Jahanian if (HasCopyAndDispose) 5255e1f84f8e4cd02347ab0e74eb8f328b3bcacb369cFariborz Jahanian flags |= BLOCK_HAS_COPY_DISPOSE; 525652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian Name = ND->getNameAsString(); 5257a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType.clear(); 5258a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 52592663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian std::string ForwardingCastType("("); 52602663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian ForwardingCastType += ByrefType + " *)"; 526152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian if (!hasInit) { 52622086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian ByrefType += " " + Name + " = {(void*)"; 52632086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian ByrefType += utostr(isa); 52642663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 5265ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flags); 5266f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ByrefType += ", "; 5267a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += "sizeof("; 5268a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 5269a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += ")"; 5270d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian if (HasCopyAndDispose) { 5271ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += ", __Block_byref_id_object_copy_"; 5272ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flag); 5273ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += ", __Block_byref_id_object_dispose_"; 5274ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flag); 5275d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 527652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += "};\n"; 5277822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian unsigned nameSize = Name.size(); 5278822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian // for block or function pointer declaration. Name is aleady 5279822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian // part of the declaration. 5280822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) 5281822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian nameSize = 1; 5282822ac874ae99f326b59eb340bd47e96f69c0cf3bFariborz Jahanian ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType); 528352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian } 528452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian else { 5285dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian SourceLocation startLoc; 5286dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian Expr *E = ND->getInit(); 5287dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 5288dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian startLoc = ECE->getLParenLoc(); 5289dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian else 5290dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian startLoc = E->getLocStart(); 5291402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth startLoc = SM->getExpansionLoc(startLoc); 5292dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian endBuf = SM->getCharacterData(startLoc); 529352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " " + Name; 5294dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian ByrefType += " = {(void*)"; 52952086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian ByrefType += utostr(isa); 52962663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 5297ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flags); 5298f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ByrefType += ", "; 5299a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += "sizeof("; 5300a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 5301a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += "), "; 5302d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian if (HasCopyAndDispose) { 5303ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += "__Block_byref_id_object_copy_"; 5304ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flag); 5305ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += ", __Block_byref_id_object_dispose_"; 5306ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flag); 5307ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += ", "; 5308d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 5309d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); 5310c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff 5311c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // Complete the newly synthesized compound expression by inserting a right 5312c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // curly brace before the end of the declaration. 5313c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // FIXME: This approach avoids rewriting the initializer expression. It 5314c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // also assumes there is only one declarator. For example, the following 5315c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // isn't currently supported by this routine (in general): 5316c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // 5317c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37; 5318c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // 53195f371ee49c11ced954ee2c805ff1adfdcef94774Fariborz Jahanian const char *startInitializerBuf = SM->getCharacterData(startLoc); 53205f371ee49c11ced954ee2c805ff1adfdcef94774Fariborz Jahanian const char *semiBuf = strchr(startInitializerBuf, ';'); 5321c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'"); 5322c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff SourceLocation semiLoc = 53235f371ee49c11ced954ee2c805ff1adfdcef94774Fariborz Jahanian startLoc.getFileLocWithOffset(semiBuf-startInitializerBuf); 5324c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff 5325d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(semiLoc, "}"); 532652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian } 53271be6b460d5aa4dda4274a15eeba824dfd4ad10d0Fariborz Jahanian return; 53281be6b460d5aa4dda4274a15eeba824dfd4ad10d0Fariborz Jahanian} 53291be6b460d5aa4dda4274a15eeba824dfd4ad10d0Fariborz Jahanian 53301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { 533154055232a5ddb9529726e934301b125cb720a273Steve Naroff // Add initializers for any closure decl refs. 533254055232a5ddb9529726e934301b125cb720a273Steve Naroff GetBlockDeclRefExprs(Exp->getBody()); 533354055232a5ddb9529726e934301b125cb720a273Steve Naroff if (BlockDeclRefs.size()) { 533454055232a5ddb9529726e934301b125cb720a273Steve Naroff // Unique all "by copy" declarations. 533554055232a5ddb9529726e934301b125cb720a273Steve Naroff for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 5336bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (!BlockDeclRefs[i]->isByRef()) { 5337bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 5338bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 5339bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); 5340bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian } 5341bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian } 534254055232a5ddb9529726e934301b125cb720a273Steve Naroff // Unique all "by ref" declarations. 534354055232a5ddb9529726e934301b125cb720a273Steve Naroff for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 534454055232a5ddb9529726e934301b125cb720a273Steve Naroff if (BlockDeclRefs[i]->isByRef()) { 5345bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 5346bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 5347bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); 5348bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian } 534954055232a5ddb9529726e934301b125cb720a273Steve Naroff } 535054055232a5ddb9529726e934301b125cb720a273Steve Naroff // Find any imported blocks...they will need special attention. 535154055232a5ddb9529726e934301b125cb720a273Steve Naroff for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 53524fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian if (BlockDeclRefs[i]->isByRef() || 53534fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 53545b011b050e764fe1c2a38bd81b386fc6e66eeb93Fariborz Jahanian BlockDeclRefs[i]->getType()->isBlockPointerType()) 535554055232a5ddb9529726e934301b125cb720a273Steve Naroff ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); 535654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 535754055232a5ddb9529726e934301b125cb720a273Steve Naroff} 535854055232a5ddb9529726e934301b125cb720a273Steve Naroff 53595f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerFunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) { 5360fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff IdentifierInfo *ID = &Context->Idents.get(name); 536172564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); 5362ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), 5363ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), ID, FType, 0, SC_Extern, 5364d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false, false); 5365fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5366fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 53675e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz JahanianStmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, 53685f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) { 536905318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian const BlockDecl *block = Exp->getBlockDecl(); 5370fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Blocks.push_back(Exp); 5371fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5372fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CollectBlockDeclRefInfo(Exp); 53735e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 53745e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // Add inner imported variables now used in current block. 53755e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian int countOfInnerDecls = 0; 53761276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian if (!InnerBlockDeclRefs.empty()) { 53771276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { 53781276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i]; 53791276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian ValueDecl *VD = Exp->getDecl(); 53801276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) { 53815e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // We need to save the copied-in variables in nested 53825e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // blocks because it is needed at the end for some of the API generations. 53835e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // See SynthesizeBlockLiterals routine. 53841276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 53851276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockDeclRefs.push_back(Exp); 53861276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockByCopyDeclsPtrSet.insert(VD); 53871276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockByCopyDecls.push_back(VD); 53881276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian } 53891276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) { 53901276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 53911276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockDeclRefs.push_back(Exp); 53921276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockByRefDeclsPtrSet.insert(VD); 53931276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockByRefDecls.push_back(VD); 53941276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian } 5395f89c4270c94ddd966819fe6b8306aa572d1e5d83Fariborz Jahanian } 53961276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian // Find any imported blocks...they will need special attention. 53971276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) 53981276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian if (InnerBlockDeclRefs[i]->isByRef() || 53991276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 54001276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) 54011276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); 54025e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian } 54035e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerDeclRefsCount.push_back(countOfInnerDecls); 54045e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 5405fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string FuncName; 54061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5407fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (CurFunctionDef) 5408077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner FuncName = CurFunctionDef->getNameAsString(); 5409e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian else if (CurMethodDef) 5410e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian BuildUniqueMethodName(FuncName, CurMethodDef); 5411e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian else if (GlobalVarDecl) 5412d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner FuncName = std::string(GlobalVarDecl->getNameAsString()); 54131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5414fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string BlockNumber = utostr(Blocks.size()-1); 54151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5416fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber; 5417fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; 54181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5419fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Get a pointer to the function type so we can cast appropriately. 54201f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType()); 54211f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType FType = Context->getPointerType(BFT); 5422fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5423fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff FunctionDecl *FD; 5424fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Expr *NewRep; 54251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5426fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Simulate a contructor call... 54274087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FD = SynthBlockInitFunctionDecl(Tag); 5428f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, VK_RValue, 5429f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 54301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54315f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 4> InitExprs; 54321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5433fdc0372eda30952b03f3fd4269dbc4b2acfdfa55Steve Naroff // Initialize the block function. 54344087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FD = SynthBlockInitFunctionDecl(Func); 5435f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 54368189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek SourceLocation()); 54379d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 5438a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, Arg); 54391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump InitExprs.push_back(castExpr); 54401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 544101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff // Initialize the block descriptor. 544201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; 544301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 5444ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, 5445ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), SourceLocation(), 5446ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara &Context->Idents.get(DescData.c_str()), 5447ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara Context->VoidPtrTy, 0, 5448ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SC_Static, SC_None); 5449f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall UnaryOperator *DescRefExpr = 5450f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, 5451f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Context->VoidPtrTy, 5452f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_LValue, 5453f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()), 5454f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall UO_AddrOf, 5455f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Context->getPointerType(Context->VoidPtrTy), 5456f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 5457f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 545801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff InitExprs.push_back(DescRefExpr); 545901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 5460fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Add initializers for any closure decl refs. 5461fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BlockDeclRefs.size()) { 5462fdc0372eda30952b03f3fd4269dbc4b2acfdfa55Steve Naroff Expr *Exp; 5463fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Output all "by copy" declarations. 54645f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 5465fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff E = BlockByCopyDecls.end(); I != E; ++I) { 5466fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (isObjCType((*I)->getType())) { 5467fdc0372eda30952b03f3fd4269dbc4b2acfdfa55Steve Naroff // FIXME: Conform to ABI ([[obj retain] autorelease]). 54684087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FD = SynthBlockInitFunctionDecl((*I)->getName()); 5469f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 5470f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 5471a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian if (HasLocalVariableExternalStorage(*I)) { 5472a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian QualType QT = (*I)->getType(); 5473a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian QT = Context->getPointerType(QT); 5474f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 5475f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall OK_Ordinary, SourceLocation()); 5476a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian } 547701f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff } else if (isTopLevelBlockPointerType((*I)->getType())) { 54784087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FD = SynthBlockInitFunctionDecl((*I)->getName()); 5479f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 5480f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 54819d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 5482a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, Arg); 5483fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } else { 54844087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FD = SynthBlockInitFunctionDecl((*I)->getName()); 5485f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 5486f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 54876cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(*I)) { 54886cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QualType QT = (*I)->getType(); 54896cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT = Context->getPointerType(QT); 5490f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 5491f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall OK_Ordinary, SourceLocation()); 54926cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 54936cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 5494fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 54951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump InitExprs.push_back(Exp); 5496fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5497fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Output all "by ref" declarations. 54985f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 5499fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff E = BlockByRefDecls.end(); I != E; ++I) { 55002663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian ValueDecl *ND = (*I); 55012663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian std::string Name(ND->getNameAsString()); 55022663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian std::string RecName; 55031e8011e2fcddc4a638d210ec2dcd21adcf7b1763Fariborz Jahanian RewriteByRefString(RecName, Name, ND, true); 55042663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 55052663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian + sizeof("struct")); 5506465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 5507ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 5508ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara II); 55092663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); 55102663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 55112663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian 55124087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FD = SynthBlockInitFunctionDecl((*I)->getName()); 5513f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 5514f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 551505318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian bool isNestedCapturedVar = false; 551605318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian if (block) 551705318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 551805318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian ce = block->capture_end(); ci != ce; ++ci) { 551905318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian const VarDecl *variable = ci->getVariable(); 552005318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian if (variable == ND && ci->isNested()) { 552105318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian assert (ci->isByRef() && 552205318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian "SynthBlockInitExpr - captured block variable is not byref"); 552305318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian isNestedCapturedVar = true; 552405318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian break; 552505318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian } 552605318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian } 552705318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian // captured nested byref variable has its address passed. Do not take 552805318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian // its address again. 552905318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian if (!isNestedCapturedVar) 553005318d835e8beb16ac6bdd2c0db0ab6a922f35cfFariborz Jahanian Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, 5531f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Context->getPointerType(Exp->getType()), 5532f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, SourceLocation()); 5533a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); 55341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump InitExprs.push_back(Exp); 5535fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 553601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff } 5537ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian if (ImportedBlockDecls.size()) { 5538ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR 5539ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR); 554001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff unsigned IntSize = 554101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 55429996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 55439996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis Context->IntTy, SourceLocation()); 5544ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian InitExprs.push_back(FlagExp); 5545fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5546668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(), 5547f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FType, VK_LValue, SourceLocation()); 55482de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, 55491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Context->getPointerType(NewRep->getType()), 5550f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, SourceLocation()); 5551a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, 55529d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall NewRep); 5553fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff BlockDeclRefs.clear(); 5554fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff BlockByRefDecls.clear(); 5555bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByRefDeclsPtrSet.clear(); 5556fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff BlockByCopyDecls.clear(); 5557bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByCopyDeclsPtrSet.clear(); 5558fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff ImportedBlockDecls.clear(); 5559fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return NewRep; 5560fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5561fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 556242f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanianbool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { 556342f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanian if (const ObjCForCollectionStmt * CS = 556442f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanian dyn_cast<ObjCForCollectionStmt>(Stmts.back())) 556542f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanian return CS->getElement() == DS; 556642f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanian return false; 556742f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanian} 556842f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanian 5569fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff//===----------------------------------------------------------------------===// 5570fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff// Function Body / Expression rewriting 5571fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff//===----------------------------------------------------------------------===// 5572fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5573c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// This is run as a first "pass" prior to RewriteFunctionBodyOrGlobalInitializer(). 5574c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// The allows the main rewrite loop to associate all ObjCPropertyRefExprs with 5575c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// their respective BinaryOperator. Without this knowledge, we'd need to rewrite 5576c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// the ObjCPropertyRefExpr twice (once as a getter, and later as a setter). 5577c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// Since the rewriter isn't capable of rewriting rewritten code, it's important 5578c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// we get this right. 5579c77a636688e188af7e7a9a05829e542adb48e880Steve Naroffvoid RewriteObjC::CollectPropertySetters(Stmt *S) { 5580c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // Perform a bottom up traversal of all children. 55817502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 5582c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (*CI) 5583c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CollectPropertySetters(*CI); 5584c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff 5585c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { 5586c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (BinOp->isAssignmentOp()) { 558712f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall if (isa<ObjCPropertyRefExpr>(BinOp->getLHS())) 558812f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall PropSetters[BinOp->getLHS()] = BinOp; 5589c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff } 5590c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff } 5591c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff} 5592c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff 5593fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffStmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { 55941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 5595fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff isa<DoStmt>(S) || isa<ForStmt>(S)) 5596fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Stmts.push_back(S); 5597fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff else if (isa<ObjCForCollectionStmt>(S)) { 5598fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Stmts.push_back(S); 55994824fcdf37139efa57466a2a5753dd6e5e792ef8Chris Lattner ObjCBcLabelNo.push_back(++BcLabelCount); 5600fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 56011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5602fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceRange OrigStmtRange = S->getSourceRange(); 56031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5604fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Perform a bottom up rewrite of all children. 56057502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 5606fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (*CI) { 56072b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *newStmt; 56081d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian Stmt *ChildStmt = (*CI); 56091d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(ChildStmt)) { 56102b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Expr *OldBase = IvarRefExpr->getBase(); 56112b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian bool replaced = false; 56121d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian newStmt = RewriteObjCNestedIvarRefExpr(ChildStmt, replaced); 56132b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (replaced) { 56142b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt)) 56152b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian ReplaceStmt(OldBase, IRE->getBase()); 56162b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian else 56171d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian ReplaceStmt(ChildStmt, newStmt); 56182b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian } 56192b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian } 56202b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian else 56211d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian newStmt = RewriteFunctionBodyOrGlobalInitializer(ChildStmt); 56221d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian if (newStmt) { 56231d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian if (Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(ChildStmt)) 56241d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian if (PropSetters[PropOrImplicitRefExpr] == S) { 56251d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian S = newStmt; 56261d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian newStmt = 0; 56271d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian } 56281d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian if (newStmt) 56291d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian *CI = newStmt; 56301d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian } 563190fe4bc75d7fe0a68fd858b278221101787320daFariborz Jahanian // If dealing with an assignment with LHS being a property reference 563290fe4bc75d7fe0a68fd858b278221101787320daFariborz Jahanian // expression, the entire assignment tree is rewritten into a property 563390fe4bc75d7fe0a68fd858b278221101787320daFariborz Jahanian // setter messaging. This involvs the RHS too. Do not attempt to rewrite 563490fe4bc75d7fe0a68fd858b278221101787320daFariborz Jahanian // RHS again. 56351d015313b27f6002b1c4a74e478ede1622141b4eFariborz Jahanian if (Expr *Exp = dyn_cast<Expr>(ChildStmt)) 563612f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall if (isa<ObjCPropertyRefExpr>(Exp)) { 56378537f7b49402bddeac95893eb711a3912aef3552Fariborz Jahanian if (PropSetters[Exp]) { 56388537f7b49402bddeac95893eb711a3912aef3552Fariborz Jahanian ++CI; 56398537f7b49402bddeac95893eb711a3912aef3552Fariborz Jahanian continue; 56408537f7b49402bddeac95893eb711a3912aef3552Fariborz Jahanian } 564190fe4bc75d7fe0a68fd858b278221101787320daFariborz Jahanian } 56427e7492442f32e3abbe246f6bb35568b044c1188bNick Lewycky } 56431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5644fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { 56455f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs; 564672952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; 564772952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerContexts.insert(BE->getBlockDecl()); 56486cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ImportedLocalExternalDecls.clear(); 56495e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian GetInnerBlockDeclRefExprs(BE->getBody(), 565072952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerBlockDeclRefs, InnerContexts); 5651fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Rewrite the block body in place. 5652da4ad9fa26b607adde033badcf67396ebc0cfe17Fariborz Jahanian Stmt *SaveCurrentBody = CurrentBody; 5653da4ad9fa26b607adde033badcf67396ebc0cfe17Fariborz Jahanian CurrentBody = BE->getBody(); 565436178092294301d26b8c77f755dae9489a9a722cFariborz Jahanian CollectPropertySetters(CurrentBody); 5655da4ad9fa26b607adde033badcf67396ebc0cfe17Fariborz Jahanian PropParentMap = 0; 5656f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian // block literal on rhs of a property-dot-sytax assignment 5657f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian // must be replaced by its synthesize ast so getRewrittenText 5658f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian // works as expected. In this case, what actually ends up on RHS 5659f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian // is the blockTranscribed which is the helper function for the 5660f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian // block literal; as in: self.c = ^() {[ace ARR];}; 5661f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian bool saveDisableReplaceStmt = DisableReplaceStmt; 5662f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian DisableReplaceStmt = false; 5663fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); 5664f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian DisableReplaceStmt = saveDisableReplaceStmt; 5665da4ad9fa26b607adde033badcf67396ebc0cfe17Fariborz Jahanian CurrentBody = SaveCurrentBody; 5666da4ad9fa26b607adde033badcf67396ebc0cfe17Fariborz Jahanian PropParentMap = 0; 56676cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ImportedLocalExternalDecls.clear(); 5668fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Now we snarf the rewritten text and stash it away for later use. 5669f23a0ff5816cb099aea8c9e06ac8654c360cf668Fariborz Jahanian std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); 56708e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff RewrittenBlockExprs[BE] = Str; 56711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 56725e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); 56735e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 5674fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff //blockTranscribed->dump(); 56758e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff ReplaceStmt(S, blockTranscribed); 5676fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return blockTranscribed; 5677fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5678fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Handle specific things. 5679fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) 5680fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteAtEncode(AtEncode); 56811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 568212f78a6741a4cb3d904340f8d3d2714568b50e7aJohn McCall if (isa<ObjCPropertyRefExpr>(S)) { 5683f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(S); 5684f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian assert(PropOrImplicitRefExpr && "Property or implicit setter/getter is null"); 5685f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian 5686f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian BinaryOperator *BinOp = PropSetters[PropOrImplicitRefExpr]; 5687c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (BinOp) { 5688c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // Because the rewriter doesn't allow us to rewrite rewritten code, 5689c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // we need to rewrite the right hand side prior to rewriting the setter. 5690b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff DisableReplaceStmt = true; 5691b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // Save the source range. Even if we disable the replacement, the 5692b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // rewritten node will have been inserted into the tree. If the synthesized 5693b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // node is at the 'end', the rewriter will fail. Consider this: 56941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // self.errorHandler = handler ? handler : 5695b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // ^(NSURL *errorURL, NSError *error) { return (BOOL)1; }; 5696b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff SourceRange SrcRange = BinOp->getSourceRange(); 5697c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS()); 5698f2c6fa4eca6e4d3b2a005416746a47e85690f3a7Fariborz Jahanian // Need to rewrite the ivar access expression if need be. 5699f2c6fa4eca6e4d3b2a005416746a47e85690f3a7Fariborz Jahanian if (isa<ObjCIvarRefExpr>(newStmt)) { 5700f2c6fa4eca6e4d3b2a005416746a47e85690f3a7Fariborz Jahanian bool replaced = false; 5701f2c6fa4eca6e4d3b2a005416746a47e85690f3a7Fariborz Jahanian newStmt = RewriteObjCNestedIvarRefExpr(newStmt, replaced); 5702f2c6fa4eca6e4d3b2a005416746a47e85690f3a7Fariborz Jahanian } 5703f2c6fa4eca6e4d3b2a005416746a47e85690f3a7Fariborz Jahanian 5704b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff DisableReplaceStmt = false; 57054c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 57064c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // Unlike the main iterator, we explicily avoid changing 'BinOp'. If 57074c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // we changed the RHS of BinOp, the rewriter would fail (since it needs 57084c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // to see the original expression). Consider this example: 57094c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 57104c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // Foo *obj1, *obj2; 57114c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 57124c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // obj1.i = [obj2 rrrr]; 57134c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 57144c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 'BinOp' for the previous expression looks like: 57154c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 57164c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (BinaryOperator 0x231ccf0 'int' '=' 57174c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (ObjCPropertyRefExpr 0x231cc70 'int' Kind=PropertyRef Property="i" 57184c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (DeclRefExpr 0x231cc50 'Foo *' Var='obj1' 0x231cbb0)) 57194c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (ObjCMessageExpr 0x231ccb0 'int' selector=rrrr 57204c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (DeclRefExpr 0x231cc90 'Foo *' Var='obj2' 0x231cbe0))) 57214c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 57224c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 'newStmt' represents the rewritten message expression. For example: 57234c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 57244c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (CallExpr 0x231d300 'id':'struct objc_object *' 57254c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (ParenExpr 0x231d2e0 'int (*)(id, SEL)' 57264c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (CStyleCastExpr 0x231d2c0 'int (*)(id, SEL)' 57274c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (CStyleCastExpr 0x231d220 'void *' 57284c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0)))) 57294c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 5730f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // Note that 'newStmt' is passed to RewritePropertyOrImplicitSetter so that it 57314c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // can be used as the setter argument. ReplaceStmt() will still 'see' 57324c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // the original RHS (since we haven't altered BinOp). 57334c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 57341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // This implies the Rewrite* routines can no longer delete the original 57354c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // node. As a result, we now leak the original AST nodes. 57364c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 5737f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian return RewritePropertyOrImplicitSetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange); 5738c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff } else { 5739f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian return RewritePropertyOrImplicitGetter(PropOrImplicitRefExpr); 574015f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff } 574115f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff } 5742f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian 5743fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) 5744fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteAtSelector(AtSelector); 57451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5746fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) 5747fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCStringLiteral(AtString); 57481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5749fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { 5750c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff#if 0 5751fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Before we rewrite it, put the original message expression in a comment. 5752fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation startLoc = MessExpr->getLocStart(); 5753fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation endLoc = MessExpr->getLocEnd(); 57541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5755fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 5756fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff const char *endBuf = SM->getCharacterData(endLoc); 57571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5758fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string messString; 5759fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff messString += "// "; 5760fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff messString.append(startBuf, endBuf-startBuf+1); 5761fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff messString += "\n"; 57621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME: Missing definition of 5764fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // InsertText(clang::SourceLocation, char const*, unsigned int). 5765fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // InsertText(startLoc, messString.c_str(), messString.size()); 5766fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Tried this, but it didn't work either... 5767fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); 5768c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff#endif 5769fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteMessageExpr(MessExpr); 5770fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 57711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5772fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) 5773fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCTryStmt(StmtTry); 5774fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5775fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) 5776fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCSynchronizedStmt(StmtTry); 5777fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5778fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) 5779fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCThrowStmt(StmtThrow); 57801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5781fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) 5782fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCProtocolExpr(ProtocolExp); 57831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (ObjCForCollectionStmt *StmtForCollection = 5785fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff dyn_cast<ObjCForCollectionStmt>(S)) 57861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return RewriteObjCForCollectionStmt(StmtForCollection, 5787fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff OrigStmtRange.getEnd()); 5788fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BreakStmt *StmtBreakStmt = 5789fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff dyn_cast<BreakStmt>(S)) 5790fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteBreakStmt(StmtBreakStmt); 5791fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ContinueStmt *StmtContinueStmt = 5792fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff dyn_cast<ContinueStmt>(S)) 5793fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteContinueStmt(StmtContinueStmt); 57941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 57951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls 5796fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // and cast exprs. 5797fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 5798fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // FIXME: What we're doing here is modifying the type-specifier that 5799fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // precedes the first Decl. In the future the DeclGroup should have 58001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // a separate type-specifier that we can rewrite. 58013d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // NOTE: We need to avoid rewriting the DeclStmt if it is within 58023d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // the context of an ObjCForCollectionStmt. For example: 58033d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // NSArray *someArray; 58043d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // for (id <FooProtocol> index in someArray) ; 58053d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // This is because RewriteObjCForCollectionStmt() does textual rewriting 58063d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // and it depends on the original text locations/positions. 580742f1e658765b0b3e069f52726da23517a466c582Fariborz Jahanian if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS)) 58083d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); 58091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5810fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Blocks rewrite rules. 5811fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 5812fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff DI != DE; ++DI) { 58134afa39deaa245592977136d367251ee2c173dd8dDouglas Gregor Decl *SD = *DI; 5814fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { 581501f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(ND->getType())) 5816fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteBlockPointerDecl(ND); 58171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (ND->getType()->isFunctionPointerType()) 5818fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CheckFunctionPointerDecl(ND->getType(), ND); 58194c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { 5820a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian if (VD->hasAttr<BlocksAttr>()) { 5821a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian static unsigned uniqueByrefDeclCount = 0; 5822a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian assert(!BlockByRefDeclNo.count(ND) && 5823a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); 5824a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; 582552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian RewriteByRefVar(VD); 5826a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian } 58274c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian else 58284c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian RewriteTypeOfDecl(VD); 58294c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 5830fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5831162e1c1b487352434552147967c3dd296ebee2f7Richard Smith if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { 583201f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 5833fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteBlockPointerDecl(TD); 58341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (TD->getUnderlyingType()->isFunctionPointerType()) 5835fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 5836fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5837fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5838fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 58391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5840fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) 5841fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteObjCQualifiedInterfaceTypes(CE); 58421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 58431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 5844fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff isa<DoStmt>(S) || isa<ForStmt>(S)) { 5845fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff assert(!Stmts.empty() && "Statement stack is empty"); 58461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 58471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 5848fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff && "Statement stack mismatch"); 5849fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Stmts.pop_back(); 5850fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5851fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Handle blocks rewriting. 5852fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) { 5853fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BDRE->isByRef()) 5854621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return RewriteBlockDeclRefExpr(BDRE); 5855fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5856f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 5857f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ValueDecl *VD = DRE->getDecl(); 5858f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian if (VD->hasAttr<BlocksAttr>()) 5859f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian return RewriteBlockDeclRefExpr(DRE); 58606cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(VD)) 58616cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return RewriteLocalVariableExternalStorage(DRE); 5862f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian } 5863f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian 5864fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 5865aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff if (CE->getCallee()->getType()->isBlockPointerType()) { 58668a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); 5867aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff ReplaceStmt(S, BlockCall); 5868aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff return BlockCall; 5869aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff } 5870fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5871b2f9e516327310d95840d442416084508f80c183Steve Naroff if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) { 5872fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteCastExpr(CE); 5873fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5874fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff#if 0 5875fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 5876906082edf2aea1c6de2926f93a8d7121e49d2a54Sebastian Redl CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), 5877906082edf2aea1c6de2926f93a8d7121e49d2a54Sebastian Redl ICE->getSubExpr(), 5878906082edf2aea1c6de2926f93a8d7121e49d2a54Sebastian Redl SourceLocation()); 5879fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Get the new text. 5880fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string SStr; 5881fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff llvm::raw_string_ostream Buf(SStr); 58823a9eb44f2906e44ca29ae2d9df56fb9824ef7d05Eli Friedman Replacement->printPretty(Buf, *Context); 5883fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff const std::string &Str = Buf.str(); 5884fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5885fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff printf("CAST = %s\n", &Str[0]); 5886fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size()); 5887fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff delete S; 5888fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return Replacement; 5889fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5890fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff#endif 5891fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Return this stmt unmodified. 5892fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return S; 5893fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5894fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 58953d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroffvoid RewriteObjC::RewriteRecordBody(RecordDecl *RD) { 58963d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff for (RecordDecl::field_iterator i = RD->field_begin(), 58973d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff e = RD->field_end(); i != e; ++i) { 58983d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff FieldDecl *FD = *i; 58993d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff if (isTopLevelBlockPointerType(FD->getType())) 59003d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteBlockPointerDecl(FD); 59013d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff if (FD->getType()->isObjCQualifiedIdType() || 59023d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff FD->getType()->isObjCQualifiedInterfaceType()) 59033d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteObjCQualifiedInterfaceTypes(FD); 59043d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff } 59053d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff} 59063d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff 5907fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// HandleDeclInMainFile - This is called for each top-level decl defined in the 5908fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// main file of the input. 5909fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroffvoid RewriteObjC::HandleDeclInMainFile(Decl *D) { 5910fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 5911cb73530987a22a6877039b9404b29aba3bf226e0Steve Naroff if (FD->isOverloadedOperator()) 5912cb73530987a22a6877039b9404b29aba3bf226e0Steve Naroff return; 59131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5914fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Since function prototypes don't have ParmDecl's, we check the function 5915fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // prototype. This enables us to rewrite function declarations and 5916fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // definitions using the same code. 591772564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor RewriteBlocksInFunctionProtoType(FD->getType(), FD); 5918fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5919d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // FIXME: If this should support Obj-C++, support CXXTryStmt 59205f1bfc10a12d9759444eb433f52a85d2e0058967Argyrios Kyrtzidis if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { 5921fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CurFunctionDef = FD; 5922abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = FD; 5923c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CollectPropertySetters(Body); 59248599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = Body; 5925eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek Body = 5926eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 5927eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek FD->setBody(Body); 59288599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = 0; 59298599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (PropParentMap) { 59308599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff delete PropParentMap; 59318599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropParentMap = 0; 59328599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 5933fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // This synthesizes and inserts the block "impl" struct, invoke function, 5934fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // and any copy/dispose helper functions. 5935fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff InsertBlockLiteralsWithinFunction(FD); 5936fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CurFunctionDef = 0; 5937abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 59381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 5939fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 5940fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5941fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 59426fb0aee4f9dc261bbec72e1283ad8dc0557a6d96Argyrios Kyrtzidis if (CompoundStmt *Body = MD->getCompoundBody()) { 5943fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CurMethodDef = MD; 5944c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CollectPropertySetters(Body); 59458599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = Body; 5946eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek Body = 5947eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 5948eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek MD->setBody(Body); 59498599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = 0; 59508599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (PropParentMap) { 59518599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff delete PropParentMap; 59528599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropParentMap = 0; 59538599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 5954fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff InsertBlockLiteralsWithinMethod(MD); 5955fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CurMethodDef = 0; 5956fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5957fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5958fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCImplementationDecl *CI = dyn_cast<ObjCImplementationDecl>(D)) 5959fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff ClassImplementation.push_back(CI); 5960fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff else if (ObjCCategoryImplDecl *CI = dyn_cast<ObjCCategoryImplDecl>(D)) 5961fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CategoryImplementation.push_back(CI); 596295ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian else if (isa<ObjCClassDecl>(D)) 596395ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian assert(false && "RewriteObjC::HandleDeclInMainFile - ObjCClassDecl"); 5964fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { 5965fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteObjCQualifiedInterfaceTypes(VD); 596601f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(VD->getType())) 5967fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteBlockPointerDecl(VD); 59688e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff else if (VD->getType()->isFunctionPointerType()) { 5969fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CheckFunctionPointerDecl(VD->getType(), VD); 5970fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (VD->getInit()) { 5971b2f9e516327310d95840d442416084508f80c183Steve Naroff if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 5972fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteCastExpr(CE); 5973fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5974fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 59753d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff } else if (VD->getType()->isRecordType()) { 59763d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl(); 59773d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff if (RD->isDefinition()) 59783d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteRecordBody(RD); 5979fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 59808e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff if (VD->getInit()) { 59818e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff GlobalVarDecl = VD; 5982c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CollectPropertySetters(VD->getInit()); 59838599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = VD->getInit(); 59848e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); 59858599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = 0; 59868599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (PropParentMap) { 59878599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff delete PropParentMap; 59888599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropParentMap = 0; 59898599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 59901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), 59914087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar VD->getName()); 59928e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff GlobalVarDecl = 0; 59938e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff 59948e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff // This is needed for blocks. 5995b2f9e516327310d95840d442416084508f80c183Steve Naroff if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 59968e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff RewriteCastExpr(CE); 59978e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff } 59988e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff } 5999fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 6000fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 6001162e1c1b487352434552147967c3dd296ebee2f7Richard Smith if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 600201f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 6003fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteBlockPointerDecl(TD); 60041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (TD->getUnderlyingType()->isFunctionPointerType()) 6005fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 6006fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 6007fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 6008fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { 60093d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff if (RD->isDefinition()) 60103d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteRecordBody(RD); 6011fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 6012fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 6013fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Nothing yet. 6014fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 6015fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 6016dacbc5d46aaeea817742b8c76c987b87d2490c85Chris Lattnervoid RewriteObjC::HandleTranslationUnit(ASTContext &C) { 6017fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (Diags.hasErrorOccurred()) 6018fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 60191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6020fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteInclude(); 60211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6022621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Here's a great place to add any extra declarations that may be needed. 6023621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Write out meta data for each @protocol(<expr>). 60241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 6025621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff E = ProtocolExprDecls.end(); I != E; ++I) 6026621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff RewriteObjCProtocolMetaData(*I, "", "", Preamble); 6027621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 6028d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); 60290aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff if (ClassImplementation.size() || CategoryImplementation.size()) 60300aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff RewriteImplementations(); 6031621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 6032fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Get the buffer corresponding to MainFileID. If we haven't changed it, then 6033fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // we are done. 60341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const RewriteBuffer *RewriteBuf = 6035fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Rewrite.getRewriteBufferFor(MainFileID)) { 6036fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff //printf("Changed:\n"); 6037fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 6038fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } else { 6039d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer llvm::errs() << "No changes\n"; 6040fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 6041ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff 6042621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ClassImplementation.size() || CategoryImplementation.size() || 6043621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolExprDecls.size()) { 60440aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff // Rewrite Objective-c meta data* 60450aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff std::string ResultStr; 60460aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff SynthesizeMetaDataIntoBuffer(ResultStr); 60470aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff // Emit metadata. 60480aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff *OutFile << ResultStr; 60490aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff } 6050fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff OutFile->flush(); 6051fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 6052