RewriteObjC.cpp revision 0774ba7bb220bb22e0de06c8aa92a90ab813e988
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 { 35d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian protected: 36d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian enum { 3859b173d81b05b7d10cec8b06b3fd843230ef628cNico Weber BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 3973e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian block, ... */ 4073e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 4173e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the 4273e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian __block variable */ 4359b173d81b05b7d10cec8b06b3fd843230ef628cNico Weber BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 4473e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian helpers */ 4559b173d81b05b7d10cec8b06b3fd843230ef628cNico Weber BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 4673e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian support routines */ 4773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_BYREF_CURRENT_MAX = 256 4873e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian }; 4973e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian 5073e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian enum { 5173e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_NEEDS_FREE = (1 << 24), 5273e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_COPY_DISPOSE = (1 << 25), 5373e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_CXX_OBJ = (1 << 26), 5473e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_IS_GC = (1 << 27), 5573e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_IS_GLOBAL = (1 << 28), 5673e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_DESCRIPTOR = (1 << 29) 5773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian }; 585845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian static const int OBJC_ABI_VERSION = 7; 59d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 602c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner Rewriter Rewrite; 61d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags; 624f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff const LangOptions &LangOpts; 6301c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner ASTContext *Context; 6477cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner SourceManager *SM; 65ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis TranslationUnitDecl *TUDecl; 662b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID MainFileID; 6726de4655a38b899e0f0dcef4175032175854d1cfChris Lattner const char *MainFileStart, *MainFileEnd; 685845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian Stmt *CurrentBody; 695845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian ParentMap *PropParentMap; // created lazily. 70dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian std::string InFileName; 71dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian raw_ostream* OutFile; 72dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian std::string Preamble; 73ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian 74dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian TypeDecl *ProtocolTypeDecl; 75dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian VarDecl *GlobalVarDecl; 76dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian unsigned RewriteFailedDiag; 77dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian // ObjC string constant support. 78d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff unsigned NumObjCStringLiterals; 79dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian VarDecl *ConstantStringClassReference; 80dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian RecordDecl *NSStringRecord; 811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 82dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian // ObjC foreach break/continue generation support. 83dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian int BcLabelCount; 84dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian 85d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned TryFinallyContainsReturnDiag; 86dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian // Needed for super. 87dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian ObjCMethodDecl *CurMethodDef; 88dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian RecordDecl *SuperStructDecl; 89dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian RecordDecl *ConstantStringDecl; 90dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian 91ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff FunctionDecl *MsgSendFunctionDecl; 92874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff FunctionDecl *MsgSendSuperFunctionDecl; 9380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendStretFunctionDecl; 9480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendSuperStretFunctionDecl; 95acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian FunctionDecl *MsgSendFpretFunctionDecl; 96ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff FunctionDecl *GetClassFunctionDecl; 979bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff FunctionDecl *GetMetaClassFunctionDecl; 98d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian FunctionDecl *GetSuperClassFunctionDecl; 99934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff FunctionDecl *SelGetUidFunctionDecl; 1009698464266660346fa2da1bddc3e6404a9819b25Steve Naroff FunctionDecl *CFStringFunctionDecl; 101c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff FunctionDecl *SuperContructorFunctionDecl; 102dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian FunctionDecl *CurFunctionDef; 103dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian FunctionDecl *CurFunctionDeclToDeclareForBlock; 1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 105dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian /* Misc. containers needed for meta-data rewrite. */ 106dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; 107dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; 108dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; 109dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; 110dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls; 111dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; 112dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian SmallVector<Stmt *, 32> Stmts; 113dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian SmallVector<int, 8> ObjCBcLabelNo; 114dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian // Remember all the @protocol(<expr>) expressions. 115dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; 116dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian 117dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian llvm::DenseSet<uint64_t> CopyDestroyCache; 11854055232a5ddb9529726e934301b125cb720a273Steve Naroff 11954055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block expressions. 1205f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockExpr *, 32> Blocks; 1215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<int, 32> InnerDeclRefsCount; 1225f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockDeclRefExpr *, 32> InnerDeclRefs; 1235e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 1245f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs; 1251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12654055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block related declarations. 1275f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ValueDecl *, 8> BlockByCopyDecls; 128bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; 1295f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<ValueDecl *, 8> BlockByRefDecls; 130bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; 131a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; 13254055232a5ddb9529726e934301b125cb720a273Steve Naroff llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; 1336cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls; 1346cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 13554055232a5ddb9529726e934301b125cb720a273Steve Naroff llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; 13654055232a5ddb9529726e934301b125cb720a273Steve Naroff 1374c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // This maps an original source AST to it's rewritten form. This allows 1384c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // us to avoid rewriting the same node twice (which is very uncommon). 1394c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // This is needed to support some of the exotic property rewriting. 1404c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; 14115f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 142dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian // Needed for header files being rewritten 143dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian bool IsHeader; 144dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian bool SilenceRewriteMacroWarning; 145dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian bool objc_impl_method; 146dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian 147b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff bool DisableReplaceStmt; 1484b9c2d235fb9449e249d74f48ecfec601650de93John McCall class DisableReplaceStmtScope { 1494b9c2d235fb9449e249d74f48ecfec601650de93John McCall RewriteObjC &R; 1504b9c2d235fb9449e249d74f48ecfec601650de93John McCall bool SavedValue; 1515845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 1524b9c2d235fb9449e249d74f48ecfec601650de93John McCall public: 1534b9c2d235fb9449e249d74f48ecfec601650de93John McCall DisableReplaceStmtScope(RewriteObjC &R) 1544b9c2d235fb9449e249d74f48ecfec601650de93John McCall : R(R), SavedValue(R.DisableReplaceStmt) { 1554b9c2d235fb9449e249d74f48ecfec601650de93John McCall R.DisableReplaceStmt = true; 1564b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1574b9c2d235fb9449e249d74f48ecfec601650de93John McCall ~DisableReplaceStmtScope() { 1584b9c2d235fb9449e249d74f48ecfec601650de93John McCall R.DisableReplaceStmt = SavedValue; 1594b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 1604b9c2d235fb9449e249d74f48ecfec601650de93John McCall }; 161d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian void InitializeCommon(ASTContext &context); 1621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16377cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner public: 164e3a6198400453c0d9623207718e4942f7c111f87Ted Kremenek 165f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Top Level Driver code. 16688c2596edc8eb475e20f6033de1ea01669695a0cArgyrios Kyrtzidis virtual bool HandleTopLevelDecl(DeclGroupRef D) { 16795ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 168375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) { 169375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor if (!Class->isThisDeclarationADefinition()) { 170375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor RewriteForwardClassDecl(D); 171375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor break; 172375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor } 17395ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian } 174375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor 175bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) { 176bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor if (!Proto->isThisDeclarationADefinition()) { 177bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor RewriteForwardProtocolDecl(D); 178bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor break; 179bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor } 180bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor } 181bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor 182682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner HandleTopLevelSingleDecl(*I); 18395ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian } 18488c2596edc8eb475e20f6033de1ea01669695a0cArgyrios Kyrtzidis return true; 185682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner } 186682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner void HandleTopLevelSingleDecl(Decl *D); 1872c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner void HandleDeclInMainFile(Decl *D); 1885f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner RewriteObjC(std::string inFile, raw_ostream *OS, 189d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &D, const LangOptions &LOpts, 190c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool silenceMacroWarn); 191e452e0ffc81c6c3d79680f552f2623e6cf0956d7Ted Kremenek 192e452e0ffc81c6c3d79680f552f2623e6cf0956d7Ted Kremenek ~RewriteObjC() {} 1931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 194dacbc5d46aaeea817742b8c76c987b87d2490c85Chris Lattner virtual void HandleTranslationUnit(ASTContext &C); 1951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19688906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanian void ReplaceStmt(Stmt *Old, Stmt *New) { 1974c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff Stmt *ReplacingStmt = ReplacedNodes[Old]; 1981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1994c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff if (ReplacingStmt) 2004c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff return; // We can't rewrite the same node twice. 2014c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff 202b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (DisableReplaceStmt) 2034b9c2d235fb9449e249d74f48ecfec601650de93John McCall return; 204b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 205f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner // If replacement succeeded or warning disabled return with no warning. 20688906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanian if (!Rewrite.ReplaceStmt(Old, New)) { 2074c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff ReplacedNodes[Old] = New; 2084c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff return; 2094c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff } 2104c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff if (SilenceRewriteMacroWarning) 211dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner return; 2120a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 2130a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner << Old->getSourceRange(); 214dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner } 215b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 216b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { 2174b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (DisableReplaceStmt) 2184b9c2d235fb9449e249d74f48ecfec601650de93John McCall return; 2194b9c2d235fb9449e249d74f48ecfec601650de93John McCall 2207e7492442f32e3abbe246f6bb35568b044c1188bNick Lewycky // Measure the old text. 221b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff int Size = Rewrite.getRangeSize(SrcRange); 222b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (Size == -1) { 223b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 224b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff << Old->getSourceRange(); 225b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 226b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 227b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // Get the new text. 228b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff std::string SStr; 229b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff llvm::raw_string_ostream S(SStr); 230e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts)); 231b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff const std::string &Str = S.str(); 232b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 233b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // If replacement succeeded or warning disabled return with no warning. 234d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) { 235b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff ReplacedNodes[Old] = New; 236b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 237b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 238b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (SilenceRewriteMacroWarning) 239b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 240b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 241b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff << Old->getSourceRange(); 242b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 243b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 2445f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner void InsertText(SourceLocation Loc, StringRef Str, 245ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff bool InsertAfter = true) { 246aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner // If insertion succeeded or warning disabled return with no warning. 247d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer if (!Rewrite.InsertText(Loc, Str, InsertAfter) || 248f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner SilenceRewriteMacroWarning) 249f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner return; 2501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 251f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 252f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner } 2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 254aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner void ReplaceText(SourceLocation Start, unsigned OrigLength, 2555f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Str) { 256aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner // If removal succeeded or warning disabled return with no warning. 257d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer if (!Rewrite.ReplaceText(Start, OrigLength, Str) || 258aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner SilenceRewriteMacroWarning) 259aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner return; 2601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 261aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); 262aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner } 2631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 264f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Syntactic Rewriting. 2655845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void RewriteRecordBody(RecordDecl *RD); 266452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian void RewriteInclude(); 26795ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian void RewriteForwardClassDecl(DeclGroupRef D); 268a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG); 269375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 270a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const std::string &typedefString); 2715845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void RewriteImplementations(); 272a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 273a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCImplementationDecl *IMD, 274a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCCategoryImplDecl *CID); 275a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); 2764afa39deaa245592977136d367251ee2c173dd8dDouglas Gregor void RewriteImplementationDecl(Decl *Dcl); 2772d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 2782d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian ObjCMethodDecl *MDecl, std::string &ResultStr); 2797c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian void RewriteTypeIntoString(QualType T, std::string &ResultStr, 2807c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *&FPRetType); 281a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian void RewriteByRefString(std::string &ResultStr, const std::string &Name, 2821e8011e2fcddc4a638d210ec2dcd21adcf7b1763Fariborz Jahanian ValueDecl *VD, bool def=false); 283a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); 284a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); 285bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor void RewriteForwardProtocolDecl(DeclGroupRef D); 286bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor void RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG); 287a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteMethodDeclaration(ObjCMethodDecl *Method); 2886327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff void RewriteProperty(ObjCPropertyDecl *prop); 28909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff void RewriteFunctionDecl(FunctionDecl *FD); 290fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar void RewriteBlockPointerType(std::string& Str, QualType Type); 291fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD); 292abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); 293a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); 2944c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian void RewriteTypeOfDecl(VarDecl *VD); 2954f95b750534f2111f28434b282bcbd5656002816Steve Naroff void RewriteObjCQualifiedInterfaceTypes(Expr *E); 2965845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 297f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Expression Rewriting. 298f3473a7e48dfaaa88f58dd9304856e16754f9b1cSteve Naroff Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); 299e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); 3004b9c2d235fb9449e249d74f48ecfec601650de93John McCall Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo); 3014b9c2d235fb9449e249d74f48ecfec601650de93John McCall Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo); 302b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); 303e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); 304beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); 30536ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); 306b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void RewriteTryReturnStmts(Stmt *S); 307b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void RewriteSyncReturnStmts(Stmt *S, std::string buf); 308a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); 309a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); 310a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); 311338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 312338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner SourceLocation OrigEnd); 313e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmt *RewriteBreakStmt(BreakStmt *S); 314e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmt *RewriteContinueStmt(ContinueStmt *S); 3155845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void RewriteCastExpr(CStyleCastExpr *CE); 316d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 31754055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block rewriting. 3181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); 3195845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Block specific rewrite rules. 32154055232a5ddb9529726e934301b125cb720a273Steve Naroff void RewriteBlockPointerDecl(NamedDecl *VD); 32252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian void RewriteByRefVar(VarDecl *VD); 323f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian Stmt *RewriteBlockDeclRefExpr(Expr *VD); 3246cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); 32554055232a5ddb9529726e934301b125cb720a273Steve Naroff void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); 3265845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 3275845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 3285845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian std::string &Result); 329d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 330d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void Initialize(ASTContext &context) = 0; 331d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 332d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Metadata Rewriting. 333d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0; 334d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, 335d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef prefix, 336d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef ClassName, 337d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) = 0; 338d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 339d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) = 0; 340d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 341d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef prefix, 342d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef ClassName, 343d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) = 0; 344d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 345d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) = 0; 346d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 347d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Rewriting ivar access 348d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0; 349d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 350d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) = 0; 3515845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 3525845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian // Misc. AST transformation routines. Somtimes they end up calling 3535845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian // rewriting routines on the new ASTs. 3545845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 3555845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian Expr **args, unsigned nargs, 3565845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian SourceLocation StartLoc=SourceLocation(), 3575845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian SourceLocation EndLoc=SourceLocation()); 3581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3595845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, 3605845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian SourceLocation StartLoc=SourceLocation(), 3615845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian SourceLocation EndLoc=SourceLocation()); 3625845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 3635845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthCountByEnumWithState(std::string &buf); 3645845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthMsgSendFunctionDecl(); 3655845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthMsgSendSuperFunctionDecl(); 3665845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthMsgSendStretFunctionDecl(); 3675845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthMsgSendFpretFunctionDecl(); 3685845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthMsgSendSuperStretFunctionDecl(); 3695845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthGetClassFunctionDecl(); 3705845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthGetMetaClassFunctionDecl(); 3715845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthGetSuperClassFunctionDecl(); 3725845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthSelGetUidFunctionDecl(); 3735845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void SynthSuperContructorFunctionDecl(); 3745845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 3755845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); 3761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 3775f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef funcName, std::string Tag); 3781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string SynthesizeBlockFunc(BlockExpr *CE, int i, 3795f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef funcName, std::string Tag); 38001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string SynthesizeBlockImpl(BlockExpr *CE, 38101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string Tag, std::string Desc); 38201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string SynthesizeBlockDescriptor(std::string DescTag, 38301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string ImplTag, 3845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner int i, StringRef funcName, 38501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff unsigned hasCopy); 3868a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); 38754055232a5ddb9529726e934301b125cb720a273Steve Naroff void SynthesizeBlockLiterals(SourceLocation FunLocStart, 3885f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef FunName); 3895845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); 3905845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian Stmt *SynthBlockInitExpr(BlockExpr *Exp, 3915845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs); 3925845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 3935845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian // Misc. helper routines. 394dd8079c54b0030152c373541f6b0d3d7983ef18cFariborz Jahanian QualType getProtocolType(); 3955845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void WarnAboutReturnGotoStmts(Stmt *S); 3965845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void HasReturnStmts(Stmt *S, bool &hasReturns); 3975845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); 3985845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); 3995845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); 4001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4015845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian bool IsDeclStmtInForeachHeader(DeclStmt *DS); 40254055232a5ddb9529726e934301b125cb720a273Steve Naroff void CollectBlockDeclRefInfo(BlockExpr *Exp); 40354055232a5ddb9529726e934301b125cb720a273Steve Naroff void GetBlockDeclRefExprs(Stmt *S); 4045e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian void GetInnerBlockDeclRefExprs(Stmt *S, 4055f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs, 40672952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts); 4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 40854055232a5ddb9529726e934301b125cb720a273Steve Naroff // We avoid calling Type::isBlockPointerType(), since it operates on the 40954055232a5ddb9529726e934301b125cb720a273Steve Naroff // canonical type. We only care if the top-level type is a closure pointer. 4108189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek bool isTopLevelBlockPointerType(QualType T) { 4118189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return isa<BlockPointerType>(T); 4128189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek } 4131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4144fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// convertBlockPointerToFunctionPointer - Converts a block-pointer type 4154fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// to a function pointer type and upon success, returns true; false 4164fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// otherwise. 4174fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian bool convertBlockPointerToFunctionPointer(QualType &T) { 4184fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (isTopLevelBlockPointerType(T)) { 4194fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian const BlockPointerType *BPT = T->getAs<BlockPointerType>(); 4204fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian T = Context->getPointerType(BPT->getPointeeType()); 4214fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian return true; 4224fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian } 4234fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian return false; 4244fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian } 4254fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian 4265845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian bool needToScanForQualifiers(QualType T); 4275845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian QualType getSuperStructType(); 4285845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian QualType getConstantStringStructType(); 4295845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian QualType convertFunctionTypeOfBlocks(const FunctionType *FT); 4305845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); 4315845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 4328188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian void convertToUnqualifiedObjCType(QualType &T) { 4338188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian if (T->isObjCQualifiedIdType()) 4348188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian T = Context->getObjCIdType(); 4358188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian else if (T->isObjCQualifiedClassType()) 4368188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian T = Context->getObjCClassType(); 4378188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian else if (T->isObjCObjectPointerType() && 4383a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian T->getPointeeType()->isObjCQualifiedInterfaceType()) { 4393a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian if (const ObjCObjectPointerType * OBJPT = 4403a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian T->getAsObjCInterfacePointerType()) { 4413a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); 4423a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian T = QualType(IFaceT, 0); 4433a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian T = Context->getPointerType(T); 4443a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian } 4453a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian } 4468188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian } 4478188e5f6367714e0eda2bdf9a9710131cb15bbfbFariborz Jahanian 44854055232a5ddb9529726e934301b125cb720a273Steve Naroff // FIXME: This predicate seems like it would be useful to add to ASTContext. 44954055232a5ddb9529726e934301b125cb720a273Steve Naroff bool isObjCType(QualType T) { 45054055232a5ddb9529726e934301b125cb720a273Steve Naroff if (!LangOpts.ObjC1 && !LangOpts.ObjC2) 45154055232a5ddb9529726e934301b125cb720a273Steve Naroff return false; 4521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 45354055232a5ddb9529726e934301b125cb720a273Steve Naroff QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); 4541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 45554055232a5ddb9529726e934301b125cb720a273Steve Naroff if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || 45654055232a5ddb9529726e934301b125cb720a273Steve Naroff OCT == Context->getCanonicalType(Context->getObjCClassType())) 45754055232a5ddb9529726e934301b125cb720a273Steve Naroff return true; 4581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4596217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (const PointerType *PT = OCT->getAs<PointerType>()) { 4601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (isa<ObjCInterfaceType>(PT->getPointeeType()) || 461d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff PT->getPointeeType()->isObjCQualifiedIdType()) 46254055232a5ddb9529726e934301b125cb720a273Steve Naroff return true; 46354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 46454055232a5ddb9529726e934301b125cb720a273Steve Naroff return false; 46554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 46654055232a5ddb9529726e934301b125cb720a273Steve Naroff bool PointerTypeTakesAnyBlockArguments(QualType QT); 467e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian bool PointerTypeTakesAnyObjCQualifiedType(QualType QT); 4688189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek void GetExtentOfArgList(const char *Name, const char *&LParen, 4698189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek const char *&RParen); 4705845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian 471621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff void QuoteDoublequotes(std::string &From, std::string &To) { 4721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (unsigned i = 0; i < From.length(); i++) { 473621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (From[i] == '"') 474621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff To += "\\\""; 475621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 476621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff To += From[i]; 477621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 478621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 479e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall 480e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getSimpleFunctionType(QualType result, 481e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall const QualType *args, 482e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall unsigned numArgs, 483e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall bool variadic = false) { 48488914801a4d73e321c6f74f97df7d7b11c298bc6Fariborz Jahanian if (result == Context->getObjCInstanceType()) 48588914801a4d73e321c6f74f97df7d7b11c298bc6Fariborz Jahanian result = Context->getObjCIdType(); 486e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall FunctionProtoType::ExtProtoInfo fpi; 487e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall fpi.Variadic = variadic; 488e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall return Context->getFunctionType(result, args, numArgs, fpi); 489e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall } 4909d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall 4915845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian // Helper function: create a CStyleCastExpr with trivial type source info. 4925845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, 4935845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian CastKind Kind, Expr *E) { 4945845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); 4955845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo, 4965845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian SourceLocation(), SourceLocation()); 4975845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian } 4985845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian }; 499d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 500d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian class RewriteObjCFragileABI : public RewriteObjC { 501d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian public: 502d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 503d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCFragileABI(std::string inFile, raw_ostream *OS, 504d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DiagnosticsEngine &D, const LangOptions &LOpts, 505d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool silenceMacroWarn) : RewriteObjC(inFile, OS, 506d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian D, LOpts, 507d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian silenceMacroWarn) {} 508d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 509d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ~RewriteObjCFragileABI() {} 510d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void Initialize(ASTContext &context); 511d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 512d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Rewriting metadata 513d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian template<typename MethodIterator> 514d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 515d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian MethodIterator MethodEnd, 516d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool IsInstanceMethod, 517d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef prefix, 518d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef ClassName, 519d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result); 520d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 521d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef prefix, 522d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef ClassName, 523d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result); 524d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteObjCProtocolListMetaData( 525d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const ObjCList<ObjCProtocolDecl> &Prots, 526d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef prefix, StringRef ClassName, std::string &Result); 527d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 528d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result); 529d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteMetaDataIntoBuffer(std::string &Result); 530d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 531d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result); 532d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 533d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Rewriting ivar 534d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 535d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result); 536d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV); 537d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian }; 53877cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner} 53977cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 5401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, 5411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump NamedDecl *D) { 542f4c7371fb1d3cebcfb40abad4537bb82515704eaJohn McCall if (const FunctionProtoType *fproto 543723df245307a530da5433dfb43accf187dc3e243Abramo Bagnara = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) { 5441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), 54554055232a5ddb9529726e934301b125cb720a273Steve Naroff E = fproto->arg_type_end(); I && (I != E); ++I) 54601f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(*I)) { 54754055232a5ddb9529726e934301b125cb720a273Steve Naroff // All the args are checked/rewritten. Don't call twice! 54854055232a5ddb9529726e934301b125cb720a273Steve Naroff RewriteBlockPointerDecl(D); 54954055232a5ddb9529726e934301b125cb720a273Steve Naroff break; 55054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 55154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 55254055232a5ddb9529726e934301b125cb720a273Steve Naroff} 55354055232a5ddb9529726e934301b125cb720a273Steve Naroff 55454055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { 5556217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek const PointerType *PT = funcType->getAs<PointerType>(); 55654055232a5ddb9529726e934301b125cb720a273Steve Naroff if (PT && PointerTypeTakesAnyBlockArguments(funcType)) 55772564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); 55854055232a5ddb9529726e934301b125cb720a273Steve Naroff} 55954055232a5ddb9529726e934301b125cb720a273Steve Naroff 560b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanianstatic bool IsHeaderFile(const std::string &Filename) { 561b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian std::string::size_type DotPos = Filename.rfind('.'); 5621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 563b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian if (DotPos == std::string::npos) { 564b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // no file extension 5651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 566b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian } 5671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 568b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); 569b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // C header: .h 570b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // C++ header: .hh or .H; 571b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian return Ext == "h" || Ext == "hh" || Ext == "H"; 5721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 573b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian 5745f9e272e632e951b1efe824cd16acb4d96077930Chris LattnerRewriteObjC::RewriteObjC(std::string inFile, raw_ostream* OS, 575d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &D, const LangOptions &LOpts, 576c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool silenceMacroWarn) 577c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS), 578c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman SilenceRewriteMacroWarning(silenceMacroWarn) { 579a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff IsHeader = IsHeaderFile(inFile); 580d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 581a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff "rewriting sub-expression within a macro (may not be correct)"); 582d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie TryFinallyContainsReturnDiag = Diags.getCustomDiagID( 583d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine::Warning, 5848189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek "rewriter doesn't support user-specified control flow semantics " 5858189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek "for @try/@finally (code may not execute properly)"); 586a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff} 587a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff 588bce831b1ecda51cd1abd3c07467294ffd21f5f86Eli FriedmanASTConsumer *clang::CreateObjCRewriter(const std::string& InFile, 5895f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner raw_ostream* OS, 590d6471f7c1921c7802804ce3ff6fe9768310f72b9David Blaikie DiagnosticsEngine &Diags, 591c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman const LangOptions &LOpts, 592c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool SilenceRewriteMacroWarning) { 593d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (true /*!LOpts.ObjCNonFragileABI*/) 594d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return new RewriteObjCFragileABI(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); 595d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else { 596d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(false && "objective-C rewriter for nonfragile ABI = NYI"); 597d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return 0; 598d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 599e365c50a21cb02e0219433db0c4461566ad4a597Chris Lattner} 60077cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 601d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::InitializeCommon(ASTContext &context) { 6029e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner Context = &context; 6039e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SM = &Context->getSourceManager(); 604ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis TUDecl = Context->getTranslationUnitDecl(); 6059e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendFunctionDecl = 0; 6069e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendSuperFunctionDecl = 0; 6079e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendStretFunctionDecl = 0; 6089e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendSuperStretFunctionDecl = 0; 6099e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendFpretFunctionDecl = 0; 6109e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner GetClassFunctionDecl = 0; 6119e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner GetMetaClassFunctionDecl = 0; 612d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian GetSuperClassFunctionDecl = 0; 6139e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SelGetUidFunctionDecl = 0; 6149e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner CFStringFunctionDecl = 0; 6159e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner ConstantStringClassReference = 0; 6169e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner NSStringRecord = 0; 61754055232a5ddb9529726e934301b125cb720a273Steve Naroff CurMethodDef = 0; 61854055232a5ddb9529726e934301b125cb720a273Steve Naroff CurFunctionDef = 0; 619abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 620b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff GlobalVarDecl = 0; 6219e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SuperStructDecl = 0; 622621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolTypeDecl = 0; 6239630ec5b6785e5b6e1c71aeddcad05005beb7483Steve Naroff ConstantStringDecl = 0; 6249e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner BcLabelCount = 0; 625c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff SuperContructorFunctionDecl = 0; 626d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff NumObjCStringLiterals = 0; 62768272b86b36f89d7ceba1ec9a2826c2126adc72eSteve Naroff PropParentMap = 0; 62868272b86b36f89d7ceba1ec9a2826c2126adc72eSteve Naroff CurrentBody = 0; 629b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff DisableReplaceStmt = false; 630f292fcf6bd5118499a830e0950429effeb373c28Fariborz Jahanian objc_impl_method = false; 6311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6329e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner // Get the ID and start/end of the main file. 6339e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileID = SM->getMainFileID(); 6349e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID); 6359e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileStart = MainBuf->getBufferStart(); 6369e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileEnd = MainBuf->getBufferEnd(); 6371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6382c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions()); 6399e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner} 6409e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner 641f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 642f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner// Top Level Driver Code 643f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 644f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 645682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattnervoid RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { 646e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek if (Diags.hasErrorOccurred()) 647e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek return; 648e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek 6492c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // Two cases: either the decl could be in the main file, or it could be in a 6502c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // #included file. If the former, rewrite it now. If the later, check to see 6512c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // if we rewrote the #include/#import. 6522c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner SourceLocation Loc = D->getLocation(); 653402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth Loc = SM->getExpansionLoc(Loc); 6541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6552c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // If this is for a builtin, ignore it. 6562c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner if (Loc.isInvalid()) return; 6572c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner 658ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Look for built-in declarations that we need to refer during the rewrite. 659ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 66009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff RewriteFunctionDecl(FD); 661248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) { 662beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff // declared in <Foundation/NSString.h> 6634087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar if (FVD->getName() == "_NSConstantStringClassReference") { 664beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff ConstantStringClassReference = FVD; 665beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff return; 666beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff } 6677723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { 6687723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor if (ID->isThisDeclarationADefinition()) 6697723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor RewriteInterfaceDecl(ID); 670a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { 671423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff RewriteCategoryDecl(CD); 672a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { 673bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor if (PD->isThisDeclarationADefinition()) 674bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor RewriteProtocolDecl(PD); 675d04341000d35c8808a72838b057eed7bf13b7661Douglas Gregor } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { 676d04341000d35c8808a72838b057eed7bf13b7661Douglas Gregor // Recurse into linkage specifications 67717945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis for (DeclContext::decl_iterator DI = LSD->decls_begin(), 67817945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis DIEnd = LSD->decls_end(); 679a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian DI != DIEnd; ) { 680375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) { 681375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor if (!IFace->isThisDeclarationADefinition()) { 682375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor SmallVector<Decl *, 8> DG; 683375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor SourceLocation StartLoc = IFace->getLocStart(); 684375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor do { 685375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor if (isa<ObjCInterfaceDecl>(*DI) && 686375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() && 687375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor StartLoc == (*DI)->getLocStart()) 688375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor DG.push_back(*DI); 689375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor else 690375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor break; 691375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor 6927723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor ++DI; 693375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor } while (DI != DIEnd); 694375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor RewriteForwardClassDecl(DG); 695375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor continue; 696a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 697a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 698bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor 699bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) { 700bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor if (!Proto->isThisDeclarationADefinition()) { 701bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor SmallVector<Decl *, 8> DG; 702bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor SourceLocation StartLoc = Proto->getLocStart(); 703bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor do { 704bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor if (isa<ObjCProtocolDecl>(*DI) && 705bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() && 706bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor StartLoc == (*DI)->getLocStart()) 707bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor DG.push_back(*DI); 708bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor else 709bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor break; 710bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor 711bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor ++DI; 712bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor } while (DI != DIEnd); 713bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor RewriteForwardProtocolDecl(DG); 714bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor continue; 715bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor } 716bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor } 717bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor 718682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner HandleTopLevelSingleDecl(*DI); 719a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian ++DI; 720a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 721ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff } 722f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // If we have a decl in the main file, see if we should rewrite it. 723cf7e958483735935de6e0a64aa1e55a967116303Ted Kremenek if (SM->isFromMainFile(Loc)) 7242c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner return HandleDeclInMainFile(D); 7252c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner} 7262c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner 727f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 728f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner// Syntactic (non-AST) Rewriting Code 729f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 730f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 731b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteInclude() { 7322b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); 7335f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef MainBuf = SM->getBufferData(MainFileID); 734f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer const char *MainBufStart = MainBuf.begin(); 735f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer const char *MainBufEnd = MainBuf.end(); 736452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian size_t ImportLen = strlen("import"); 7371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 738af57b46f12e9dd48485fa27f2088f85466ee9292Fariborz Jahanian // Loop over the whole file, looking for includes. 739452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { 740452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (*BufPtr == '#') { 741452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (++BufPtr == MainBufEnd) 742452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian return; 743452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian while (*BufPtr == ' ' || *BufPtr == '\t') 744452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (++BufPtr == MainBufEnd) 745452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian return; 746452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (!strncmp(BufPtr, "import", ImportLen)) { 747452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian // replace import with include 7481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation ImportLoc = 749a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis LocStart.getLocWithOffset(BufPtr-MainBufStart); 750d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(ImportLoc, ImportLen, "include"); 751452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian BufPtr += ImportLen; 752452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 753452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 754452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 7558a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner} 7568a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 7572d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanianstatic std::string getIvarAccessString(ObjCIvarDecl *OID) { 7582d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian const ObjCInterfaceDecl *ClassDecl = OID->getContainingInterface(); 759eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff std::string S; 760eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S = "((struct "; 761eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S += ClassDecl->getIdentifier()->getName(); 762eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S += "_IMPL *)self)->"; 7635ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar S += OID->getName(); 764eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return S; 765eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff} 766eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff 767a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroffvoid RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 768a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCImplementationDecl *IMD, 769a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCCategoryImplDecl *CID) { 7707c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian static bool objcGetPropertyDefined = false; 7717c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian static bool objcSetPropertyDefined = false; 772d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff SourceLocation startLoc = PID->getLocStart(); 773d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, "// "); 774eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 775eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff assert((*startBuf == '@') && "bogus @synthesize location"); 776eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 777eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff assert((*semiBuf == ';') && "@synthesize: can't find ';'"); 7788189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek SourceLocation onePastSemiLoc = 779a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis startLoc.getLocWithOffset(semiBuf-startBuf+1); 780eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff 781eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 782eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return; // FIXME: is this correct? 7831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 784eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff // Generate the 'getter' function. 785eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff ObjCPropertyDecl *PD = PID->getPropertyDecl(); 786eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); 7871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 788dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff if (!OID) 789dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff return; 7907c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian unsigned Attributes = PD->getPropertyAttributes(); 791ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (!PD->getGetterMethodDecl()->isDefined()) { 792ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) && 793ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian (Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 794ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_copy)); 795ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian std::string Getr; 796ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (GenGetProperty && !objcGetPropertyDefined) { 797ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian objcGetPropertyDefined = true; 798ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // FIXME. Is this attribute correct in all cases? 799ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr = "\nextern \"C\" __declspec(dllimport) " 800ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian "id objc_getProperty(id, SEL, long, bool);\n"; 801ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } 802ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian RewriteObjCMethodDecl(OID->getContainingInterface(), 803ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian PD->getGetterMethodDecl(), Getr); 804ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "{ "; 805ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // Synthesize an explicit cast to gain access to the ivar. 806ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // See objc-act.c:objc_synthesize_new_getter() for details. 807ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (GenGetProperty) { 808ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) 809ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "typedef "; 810ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian const FunctionType *FPRetType = 0; 811ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr, 812ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian FPRetType); 813ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += " _TYPE"; 814ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (FPRetType) { 815ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ")"; // close the precedence "scope" for "*". 8167c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 817ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian // Now, emit the argument types (if any). 818ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){ 819ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "("; 820ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 821ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (i) Getr += ", "; 822ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian std::string ParamStr = FT->getArgType(i).getAsString( 82330c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor Context->getPrintingPolicy()); 824ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ParamStr; 825ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } 826ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (FT->isVariadic()) { 827ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (FT->getNumArgs()) Getr += ", "; 828ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "..."; 829ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } 830ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ")"; 831ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } else 832ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "()"; 833ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian } 834ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ";\n"; 835ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "return (_TYPE)"; 836ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "objc_getProperty(self, _cmd, "; 8375845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian RewriteIvarOffsetComputation(OID, Getr); 838ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += ", 1)"; 8397c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 840ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian else 841ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "return " + getIvarAccessString(OID); 842ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian Getr += "; }"; 843ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian InsertText(onePastSemiLoc, Getr); 8447c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 845ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian 846ec3683b3f33beda2449b4896b1a9548ab283e0e7Fariborz Jahanian if (PD->isReadOnly() || PD->getSetterMethodDecl()->isDefined()) 847eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return; 8481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 849eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff // Generate the 'setter' function. 850eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff std::string Setr; 8517c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 8527c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_copy); 8537c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (GenSetProperty && !objcSetPropertyDefined) { 8547c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian objcSetPropertyDefined = true; 8557c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian // FIXME. Is this attribute correct in all cases? 8567c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr = "\nextern \"C\" __declspec(dllimport) " 8577c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian "void objc_setProperty (id, SEL, long, id, bool, bool);\n"; 8587c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8597c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 8602d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian RewriteObjCMethodDecl(OID->getContainingInterface(), 8612d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian PD->getSetterMethodDecl(), Setr); 862eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff Setr += "{ "; 863dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff // Synthesize an explicit cast to initialize the ivar. 86415f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff // See objc-act.c:objc_synthesize_new_setter() for details. 8657c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (GenSetProperty) { 8667c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "objc_setProperty (self, _cmd, "; 8675845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian RewriteIvarOffsetComputation(OID, Setr); 8687c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += ", (id)"; 8694087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar Setr += PD->getName(); 8707c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += ", "; 8717c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) 8727c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "0, "; 8737c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else 8747c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "1, "; 8757c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (Attributes & ObjCPropertyDecl::OBJC_PR_copy) 8767c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "1)"; 8777c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else 8787c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "0)"; 8797c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8807c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else { 8812d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian Setr += getIvarAccessString(OID) + " = "; 8824087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar Setr += PD->getName(); 8837c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 884dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff Setr += "; }"; 885d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, Setr); 886d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff} 8878a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 888a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanianstatic void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, 889a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian std::string &typedefString) { 890a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "#ifndef _REWRITER_typedef_"; 891a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 892a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "\n"; 893a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "#define _REWRITER_typedef_"; 894a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 895a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "\n"; 896a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "typedef struct objc_object "; 897a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 898a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ";\n#endif\n"; 899a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian} 900a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian 901375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregorvoid RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 902a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const std::string &typedefString) { 903375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor SourceLocation startLoc = ClassDecl->getLocStart(); 904a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 905a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const char *semiPtr = strchr(startBuf, ';'); 906a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian // Replace the @class with typedefs corresponding to the classes. 907a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); 908a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian} 909a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian 91095ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanianvoid RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) { 911f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner std::string typedefString; 91295ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 913375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I); 91495ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian if (I == D.begin()) { 915a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian // Translate to typedef's that forward reference structs with the same name 916a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian // as the class. As a convenience, we include the original declaration 917a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian // as a comment. 91895ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian typedefString += "// @class "; 91995ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 92091fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian typedefString += ";\n"; 92195ed7784a335aca53b0c6e952cf31a4cfb633360Fariborz Jahanian } 922a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian RewriteOneForwardClassDecl(ForwardDecl, typedefString); 923934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff } 924a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian DeclGroupRef::iterator I = D.begin(); 925375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString); 926a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian} 9271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 928a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanianvoid RewriteObjC::RewriteForwardClassDecl( 929a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian const llvm::SmallVector<Decl*, 8> &D) { 930a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian std::string typedefString; 931a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian for (unsigned i = 0; i < D.size(); i++) { 932375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]); 933a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian if (i == 0) { 934a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += "// @class "; 935a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 936a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian typedefString += ";\n"; 937a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 938a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian RewriteOneForwardClassDecl(ForwardDecl, typedefString); 939a5e2b23b594a03a5ab846ec9433a720cb3f3cc3aFariborz Jahanian } 940375bb1413c041055262c8a416f20d10474a5eda9Douglas Gregor RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString); 941f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner} 942f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 943b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { 944d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian // When method is a synthesized one, such as a getter/setter there is 945d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian // nothing to rewrite. 94688914801a4d73e321c6f74f97df7d7b11c298bc6Fariborz Jahanian if (Method->isImplicit()) 947d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian return; 94858dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff SourceLocation LocStart = Method->getLocStart(); 94958dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff SourceLocation LocEnd = Method->getLocEnd(); 9501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 951642116259e8df6286063a17361c20e95b5017a0aChandler Carruth if (SM->getExpansionLineNumber(LocEnd) > 952642116259e8df6286063a17361c20e95b5017a0aChandler Carruth SM->getExpansionLineNumber(LocStart)) { 953d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LocStart, "#if 0\n"); 954d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocEnd, 1, ";\n#endif\n"); 95558dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff } else { 956d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LocStart, "// "); 957423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff } 958423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff} 959423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff 9601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) { 961d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian SourceLocation Loc = prop->getAtLoc(); 9621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 963d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(Loc, 0, "// "); 9646327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff // FIXME: handle properties that are declared across multiple lines. 965957cf65bf32fe7c84886a2296d0b4ede40029850Fariborz Jahanian} 966957cf65bf32fe7c84886a2296d0b4ede40029850Fariborz Jahanian 967b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { 968423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff SourceLocation LocStart = CatDecl->getLocStart(); 9691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 970423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff // FIXME: handle category headers that are declared across multiple lines. 971d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 9721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97313751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), 97413751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian E = CatDecl->prop_end(); I != E; ++I) 97513751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian RewriteProperty(*I); 97613751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian 9771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCCategoryDecl::instmeth_iterator 9781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); 9796ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 98058dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 9811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCCategoryDecl::classmeth_iterator 98217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); 9836ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 98458dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 98558dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 986423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff // Lastly, comment out the @end. 98773d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(CatDecl->getAtEndRange().getBegin(), 98873d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian strlen("@end"), "/* @end */"); 989423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff} 990423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff 991b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { 992752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff SourceLocation LocStart = PDecl->getLocStart(); 99361cc296de6c1f82fa84c0abb3ecd142a584838efDouglas Gregor assert(PDecl->isThisDeclarationADefinition()); 99461cc296de6c1f82fa84c0abb3ecd142a584838efDouglas Gregor 995752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff // FIXME: handle protocol headers that are declared across multiple lines. 996d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 9971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCProtocolDecl::instmeth_iterator 9991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 10006ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 100158dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 10026ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor for (ObjCProtocolDecl::classmeth_iterator 100317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 10046ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 100558dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 100658dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 100707acdf4c776fd98e315bc1de380af8ba3c25559eFariborz Jahanian for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(), 100807acdf4c776fd98e315bc1de380af8ba3c25559eFariborz Jahanian E = PDecl->prop_end(); I != E; ++I) 100907acdf4c776fd98e315bc1de380af8ba3c25559eFariborz Jahanian RewriteProperty(*I); 101007acdf4c776fd98e315bc1de380af8ba3c25559eFariborz Jahanian 1011752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff // Lastly, comment out the @end. 1012782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); 101373d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(LocEnd, strlen("@end"), "/* @end */"); 10148cc764c67afc249628ba4f65b8e2d2ad461112ffSteve Naroff 1015b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian // Must comment out @optional/@required 1016b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 1017b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1018b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian for (const char *p = startBuf; p < endBuf; p++) { 1019b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { 1020a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 1021d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); 10221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1023b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1024b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { 1025a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 1026d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); 10271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1028b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1029b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1030752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff} 1031752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff 1032bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregorvoid RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) { 1033bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor SourceLocation LocStart = (*D.begin())->getLocStart(); 1034bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor if (LocStart.isInvalid()) 1035bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor llvm_unreachable("Invalid SourceLocation"); 1036bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor // FIXME: handle forward protocol that are declared across multiple lines. 1037bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor ReplaceText(LocStart, 0, "// "); 1038bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor} 1039bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor 1040bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregorvoid 1041bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas GregorRewriteObjC::RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG) { 1042bd9482d859a74bf2c45ef8b8aedec61c0e1c8374Douglas Gregor SourceLocation LocStart = DG[0]->getLocStart(); 1043b7fa992be16668b61f722e6e125137216860469eSteve Naroff if (LocStart.isInvalid()) 1044b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("Invalid SourceLocation"); 1045d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian // FIXME: handle forward protocol that are declared across multiple lines. 1046d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 1047d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian} 1048d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian 10497c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanianvoid RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr, 10507c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *&FPRetType) { 10517c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (T->isObjCQualifiedIdType()) 1052c569249ca0ab755ac79d8cbbfcb2bcae19743624Fariborz Jahanian ResultStr += "id"; 10537c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else if (T->isFunctionPointerType() || 10547c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian T->isBlockPointerType()) { 105576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // needs special handling, since pointer-to-functions have special 105676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // syntax (where a decaration models use). 10577c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian QualType retType = T; 1058f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff QualType PointeeTy; 10596217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (const PointerType* PT = retType->getAs<PointerType>()) 1060f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff PointeeTy = PT->getPointeeType(); 10616217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) 1062f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff PointeeTy = BPT->getPointeeType(); 1063183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall if ((FPRetType = PointeeTy->getAs<FunctionType>())) { 1064fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += FPRetType->getResultType().getAsString( 106530c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor Context->getPrintingPolicy()); 1066f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff ResultStr += "(*"; 106776e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 106876e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } else 106930c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor ResultStr += T.getAsString(Context->getPrintingPolicy()); 10707c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian} 10717c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 10722d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanianvoid RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 10732d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian ObjCMethodDecl *OMD, 10747c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian std::string &ResultStr) { 10757c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian //fprintf(stderr,"In RewriteObjCMethodDecl\n"); 10767c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *FPRetType = 0; 10777c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian ResultStr += "\nstatic "; 10787c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType); 1079531a1ea2f4c88817f3dc0f4628dfc34536f54c5eFariborz Jahanian ResultStr += " "; 10801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 108148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Unique method name 1082b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian std::string NameStr; 10831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1084f8d49f64ef6ab7e632717a31631fc289aab69428Douglas Gregor if (OMD->isInstanceMethod()) 1085b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_I_"; 108648a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian else 1087b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_C_"; 10881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10892d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian NameStr += IDecl->getNameAsString(); 1090b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_"; 10911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (ObjCCategoryImplDecl *CID = 10933e0a540b6d846178857289ec0eb8470a278d11a3Steve Naroff dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 1094d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner NameStr += CID->getNameAsString(); 1095b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_"; 109648a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 10971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Append selector names, replacing ':' with '_' 1098077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner { 1099077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner std::string selString = OMD->getSelector().getAsString(); 110048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian int len = selString.size(); 110148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian for (int i = 0; i < len; i++) 110248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian if (selString[i] == ':') 110348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian selString[i] = '_'; 1104b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += selString; 110548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 1106b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian // Remember this name for metadata emission 1107b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian MethodInternalNames[OMD] = NameStr; 1108b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian ResultStr += NameStr; 11091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Rewrite arguments 111148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += "("; 11121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // invisible arguments 1114f8d49f64ef6ab7e632717a31631fc289aab69428Douglas Gregor if (OMD->isInstanceMethod()) { 11152d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian QualType selfTy = Context->getObjCInterfaceType(IDecl); 111648a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian selfTy = Context->getPointerType(selfTy); 111762ec1f2fd7368542bb926c04797fb07023547694Francois Pichet if (!LangOpts.MicrosoftExt) { 11182d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl))) 111905b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff ResultStr += "struct "; 112005b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff } 112105b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff // When rewriting for Microsoft, explicitly omit the structure name. 11222d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian ResultStr += IDecl->getNameAsString(); 112361ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff ResultStr += " *"; 112448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 112548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian else 1126fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += Context->getObjCClassType().getAsString( 112730c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor Context->getPrintingPolicy()); 11281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += " self, "; 113030c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy()); 113148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += " _cmd"; 11321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 113348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Method arguments. 113489951a86b594513c2a013532ed45d197413b1087Chris Lattner for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 113589951a86b594513c2a013532ed45d197413b1087Chris Lattner E = OMD->param_end(); PI != E; ++PI) { 113689951a86b594513c2a013532ed45d197413b1087Chris Lattner ParmVarDecl *PDecl = *PI; 113748a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += ", "; 1138543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff if (PDecl->getType()->isObjCQualifiedIdType()) { 1139543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff ResultStr += "id "; 1140d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += PDecl->getNameAsString(); 1141543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff } else { 1142d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = PDecl->getNameAsString(); 11434fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian QualType QT = PDecl->getType(); 11444fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian // Make sure we convert "t (^)(...)" to "t (*)(...)". 11454fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (convertBlockPointerToFunctionPointer(QT)) 114630c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 11474fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian else 114830c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor PDecl->getType().getAsStringInternal(Name, Context->getPrintingPolicy()); 1149543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff ResultStr += Name; 1150543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff } 115148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 11527c39ff7eb3dd7ae9b2b81cb66a139c9b52f47f1dFariborz Jahanian if (OMD->isVariadic()) 11537c39ff7eb3dd7ae9b2b81cb66a139c9b52f47f1dFariborz Jahanian ResultStr += ", ..."; 1154531a1ea2f4c88817f3dc0f4628dfc34536f54c5eFariborz Jahanian ResultStr += ") "; 11551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FPRetType) { 115776e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ")"; // close the precedence "scope" for "*". 11581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115976e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // Now, emit the argument types (if any). 116072564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { 116176e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "("; 116276e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 116376e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (i) ResultStr += ", "; 1164fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string ParamStr = FT->getArgType(i).getAsString( 116530c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor Context->getPrintingPolicy()); 116676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ParamStr; 116776e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 116876e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FT->isVariadic()) { 116976e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FT->getNumArgs()) ResultStr += ", "; 117076e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "..."; 117176e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 117276e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ")"; 117376e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } else { 117476e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "()"; 117576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 117676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 117748a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian} 11784afa39deaa245592977136d367251ee2c173dd8dDouglas Gregorvoid RewriteObjC::RewriteImplementationDecl(Decl *OID) { 1179a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); 1180a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); 11811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1182a135216595c00ddb5ce5f5b853a3d1f4037a13b7Fariborz Jahanian InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// "); 11831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1184a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek for (ObjCCategoryImplDecl::instmeth_iterator 118517945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), 118617945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); 1187653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 118848a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian std::string ResultStr; 1189a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *OMD = *I; 11902d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 119148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian SourceLocation LocStart = OMD->getLocStart(); 11926fb0aee4f9dc261bbec72e1283ad8dc0557a6d96Argyrios Kyrtzidis SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 1193d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 119448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 119548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1196d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, ResultStr); 119748a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 11981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1199a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek for (ObjCCategoryImplDecl::classmeth_iterator 120017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), 120117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); 1202653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 120348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian std::string ResultStr; 1204a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *OMD = *I; 12052d8c1fdef9658d7c3d56bcfd5533188f6c8b6bf5Fariborz Jahanian RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 120648a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian SourceLocation LocStart = OMD->getLocStart(); 12076fb0aee4f9dc261bbec72e1283ad8dc0557a6d96Argyrios Kyrtzidis SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 12081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 120948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 121048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1211d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, ResultStr); 121248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 1213d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff for (ObjCCategoryImplDecl::propimpl_iterator 121417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), 12151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); 1216653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 1217a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff RewritePropertyImplDecl(*I, IMD, CID); 1218d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff } 1219d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff 1220d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// "); 122148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian} 122248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian 1223b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 1224f908a87299d278164540f90b5b6e6cab7b14fb41Steve Naroff std::string ResultStr; 12257723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) { 12266c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff // we haven't seen a forward decl - generate a typedef. 12275086a8df9a269acc2e4f0deb1895d4a9e9d13f4dSteve Naroff ResultStr = "#ifndef _REWRITER_typedef_"; 1228d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 122932174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "\n"; 123032174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "#define _REWRITER_typedef_"; 1231d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 123232174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "\n"; 123361ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff ResultStr += "typedef struct objc_object "; 1234d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 123532174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += ";\n#endif\n"; 12366c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff // Mark this typedef as having been generated. 12377723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl()); 12386c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff } 12395845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian RewriteObjCInternalStruct(ClassDecl, ResultStr); 12401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), 124217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = ClassDecl->prop_end(); I != E; ++I) 12436327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff RewriteProperty(*I); 12441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::instmeth_iterator 124517945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); 12466ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 124758dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 12481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::classmeth_iterator 12491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); 12506ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 125158dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 125258dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 12532feac5e559ca5c9693a3a19905ab106b9c52e193Steve Naroff // Lastly, comment out the @end. 125473d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), 125573d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian "/* @end */"); 1256bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff} 1257bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff 12584b9c2d235fb9449e249d74f48ecfec601650de93John McCallStmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) { 12594b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceRange OldRange = PseudoOp->getSourceRange(); 12604b9c2d235fb9449e249d74f48ecfec601650de93John McCall 12614b9c2d235fb9449e249d74f48ecfec601650de93John McCall // We just magically know some things about the structure of this 12624b9c2d235fb9449e249d74f48ecfec601650de93John McCall // expression. 12634b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMessageExpr *OldMsg = 12644b9c2d235fb9449e249d74f48ecfec601650de93John McCall cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr( 12654b9c2d235fb9449e249d74f48ecfec601650de93John McCall PseudoOp->getNumSemanticExprs() - 1)); 12664b9c2d235fb9449e249d74f48ecfec601650de93John McCall 12674b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Because the rewriter doesn't allow us to rewrite rewritten code, 12684b9c2d235fb9449e249d74f48ecfec601650de93John McCall // we need to suppress rewriting the sub-statements. 12694b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *Base, *RHS; 12704b9c2d235fb9449e249d74f48ecfec601650de93John McCall { 12714b9c2d235fb9449e249d74f48ecfec601650de93John McCall DisableReplaceStmtScope S(*this); 12724b9c2d235fb9449e249d74f48ecfec601650de93John McCall 12734b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Rebuild the base expression if we have one. 12744b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base = 0; 12754b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 12764b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base = OldMsg->getInstanceReceiver(); 12774b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 12784b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 12798ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian } 12804b9c2d235fb9449e249d74f48ecfec601650de93John McCall 12814b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Rebuild the RHS. 12824b9c2d235fb9449e249d74f48ecfec601650de93John McCall RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS(); 12834b9c2d235fb9449e249d74f48ecfec601650de93John McCall RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr(); 12844b9c2d235fb9449e249d74f48ecfec601650de93John McCall RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS)); 12854b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 12864b9c2d235fb9449e249d74f48ecfec601650de93John McCall 12874b9c2d235fb9449e249d74f48ecfec601650de93John McCall // TODO: avoid this copy. 12884b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<SourceLocation, 1> SelLocs; 12894b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSelectorLocs(SelLocs); 12904b9c2d235fb9449e249d74f48ecfec601650de93John McCall 12910774ba7bb220bb22e0de06c8aa92a90ab813e988Chad Rosier ObjCMessageExpr *NewMsg = 0; 12924b9c2d235fb9449e249d74f48ecfec601650de93John McCall switch (OldMsg->getReceiverKind()) { 12934b9c2d235fb9449e249d74f48ecfec601650de93John McCall case ObjCMessageExpr::Class: 12944b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 12954b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getValueKind(), 12964b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getLeftLoc(), 12974b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getClassReceiverTypeInfo(), 12984b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSelector(), 12994b9c2d235fb9449e249d74f48ecfec601650de93John McCall SelLocs, 13004b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getMethodDecl(), 13014b9c2d235fb9449e249d74f48ecfec601650de93John McCall RHS, 13024b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getRightLoc()); 13034b9c2d235fb9449e249d74f48ecfec601650de93John McCall break; 13044b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13054b9c2d235fb9449e249d74f48ecfec601650de93John McCall case ObjCMessageExpr::Instance: 13064b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 13074b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getValueKind(), 13084b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getLeftLoc(), 13094b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base, 13104b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSelector(), 13114b9c2d235fb9449e249d74f48ecfec601650de93John McCall SelLocs, 13124b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getMethodDecl(), 13134b9c2d235fb9449e249d74f48ecfec601650de93John McCall RHS, 13144b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getRightLoc()); 13154b9c2d235fb9449e249d74f48ecfec601650de93John McCall break; 13164b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13174b9c2d235fb9449e249d74f48ecfec601650de93John McCall case ObjCMessageExpr::SuperClass: 13184b9c2d235fb9449e249d74f48ecfec601650de93John McCall case ObjCMessageExpr::SuperInstance: 13194b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 13204b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getValueKind(), 13214b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getLeftLoc(), 13224b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSuperLoc(), 13234b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 13244b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSuperType(), 13254b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSelector(), 13264b9c2d235fb9449e249d74f48ecfec601650de93John McCall SelLocs, 13274b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getMethodDecl(), 13284b9c2d235fb9449e249d74f48ecfec601650de93John McCall RHS, 13294b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getRightLoc()); 13304b9c2d235fb9449e249d74f48ecfec601650de93John McCall break; 1331f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian } 13321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13334b9c2d235fb9449e249d74f48ecfec601650de93John McCall Stmt *Replacement = SynthMessageExpr(NewMsg); 13344b9c2d235fb9449e249d74f48ecfec601650de93John McCall ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 13354b9c2d235fb9449e249d74f48ecfec601650de93John McCall return Replacement; 133615f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff} 133715f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 13384b9c2d235fb9449e249d74f48ecfec601650de93John McCallStmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) { 13394b9c2d235fb9449e249d74f48ecfec601650de93John McCall SourceRange OldRange = PseudoOp->getSourceRange(); 13404b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13414b9c2d235fb9449e249d74f48ecfec601650de93John McCall // We just magically know some things about the structure of this 13424b9c2d235fb9449e249d74f48ecfec601650de93John McCall // expression. 13434b9c2d235fb9449e249d74f48ecfec601650de93John McCall ObjCMessageExpr *OldMsg = 13444b9c2d235fb9449e249d74f48ecfec601650de93John McCall cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit()); 13454b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13464b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Because the rewriter doesn't allow us to rewrite rewritten code, 13474b9c2d235fb9449e249d74f48ecfec601650de93John McCall // we need to suppress rewriting the sub-statements. 13484b9c2d235fb9449e249d74f48ecfec601650de93John McCall Expr *Base = 0; 13494b9c2d235fb9449e249d74f48ecfec601650de93John McCall { 13504b9c2d235fb9449e249d74f48ecfec601650de93John McCall DisableReplaceStmtScope S(*this); 13514b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13524b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Rebuild the base expression if we have one. 13534b9c2d235fb9449e249d74f48ecfec601650de93John McCall if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 13544b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base = OldMsg->getInstanceReceiver(); 13554b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 13564b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 13578ac2d449820fd0df00fcbde5bf82165c1f49854dFariborz Jahanian } 13588599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 13594b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13604b9c2d235fb9449e249d74f48ecfec601650de93John McCall // Intentionally empty. 13614b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<SourceLocation, 1> SelLocs; 13624b9c2d235fb9449e249d74f48ecfec601650de93John McCall SmallVector<Expr*, 1> Args; 13634b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13640774ba7bb220bb22e0de06c8aa92a90ab813e988Chad Rosier ObjCMessageExpr *NewMsg = 0; 13654b9c2d235fb9449e249d74f48ecfec601650de93John McCall switch (OldMsg->getReceiverKind()) { 13664b9c2d235fb9449e249d74f48ecfec601650de93John McCall case ObjCMessageExpr::Class: 13674b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 13684b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getValueKind(), 13694b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getLeftLoc(), 13704b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getClassReceiverTypeInfo(), 13714b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSelector(), 13724b9c2d235fb9449e249d74f48ecfec601650de93John McCall SelLocs, 13734b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getMethodDecl(), 13744b9c2d235fb9449e249d74f48ecfec601650de93John McCall Args, 13754b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getRightLoc()); 13764b9c2d235fb9449e249d74f48ecfec601650de93John McCall break; 13774b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13784b9c2d235fb9449e249d74f48ecfec601650de93John McCall case ObjCMessageExpr::Instance: 13794b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 13804b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getValueKind(), 13814b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getLeftLoc(), 13824b9c2d235fb9449e249d74f48ecfec601650de93John McCall Base, 13834b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSelector(), 13844b9c2d235fb9449e249d74f48ecfec601650de93John McCall SelLocs, 13854b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getMethodDecl(), 13864b9c2d235fb9449e249d74f48ecfec601650de93John McCall Args, 13874b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getRightLoc()); 13884b9c2d235fb9449e249d74f48ecfec601650de93John McCall break; 13894b9c2d235fb9449e249d74f48ecfec601650de93John McCall 13904b9c2d235fb9449e249d74f48ecfec601650de93John McCall case ObjCMessageExpr::SuperClass: 13914b9c2d235fb9449e249d74f48ecfec601650de93John McCall case ObjCMessageExpr::SuperInstance: 13924b9c2d235fb9449e249d74f48ecfec601650de93John McCall NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 13934b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getValueKind(), 13944b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getLeftLoc(), 13954b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSuperLoc(), 13964b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 13974b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSuperType(), 13984b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getSelector(), 13994b9c2d235fb9449e249d74f48ecfec601650de93John McCall SelLocs, 14004b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getMethodDecl(), 14014b9c2d235fb9449e249d74f48ecfec601650de93John McCall Args, 14024b9c2d235fb9449e249d74f48ecfec601650de93John McCall OldMsg->getRightLoc()); 14034b9c2d235fb9449e249d74f48ecfec601650de93John McCall break; 14048599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 14054b9c2d235fb9449e249d74f48ecfec601650de93John McCall 14064b9c2d235fb9449e249d74f48ecfec601650de93John McCall Stmt *Replacement = SynthMessageExpr(NewMsg); 14074b9c2d235fb9449e249d74f48ecfec601650de93John McCall ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 14084b9c2d235fb9449e249d74f48ecfec601650de93John McCall return Replacement; 140915f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff} 141015f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 1411fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// SynthCountByEnumWithState - To print: 1412fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// ((unsigned int (*) 1413fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 14141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// (void *)objc_msgSend)((id)l_collection, 1415fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// sel_registerName( 14161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// "countByEnumeratingWithState:objects:count:"), 14171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// &enumState, 1418108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian/// (id *)__rw_items, (unsigned int)16) 1419fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1420fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroffvoid RewriteObjC::SynthCountByEnumWithState(std::string &buf) { 1421fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 1422fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff "id *, unsigned int))(void *)objc_msgSend)"; 1423fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "\n\t\t"; 1424fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "((id)l_collection,\n\t\t"; 1425fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; 1426fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "\n\t\t"; 1427fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "&enumState, " 1428108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian "(id *)__rw_items, (unsigned int)16)"; 1429fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 1430b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff 1431fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach 1432fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// statement to exit to its outer synthesized loop. 1433fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1434fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffStmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) { 1435fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1436fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return S; 1437fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // replace break with goto __break_label 1438fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string buf; 14391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1440fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation startLoc = S->getLocStart(); 1441fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf = "goto __break_label_"; 1442fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += utostr(ObjCBcLabelNo.back()); 1443d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, strlen("break"), buf); 14442bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff 1445fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return 0; 1446fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 1447a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian 1448fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach 1449fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// statement to continue with its inner synthesized loop. 1450fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1451fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffStmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { 1452fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1453fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return S; 1454fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // replace continue with goto __continue_label 1455fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string buf; 14561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1457fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation startLoc = S->getLocStart(); 1458fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf = "goto __continue_label_"; 1459fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += utostr(ObjCBcLabelNo.back()); 1460d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, strlen("continue"), buf); 14611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1462e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian return 0; 1463e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian} 1464e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian 1465a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. 146610d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// It rewrites: 146710d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// for ( type elem in collection) { stmts; } 14681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 146910d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// Into: 147010d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// { 14711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// type elem; 147233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// struct __objcFastEnumerationState enumState = { 0 }; 1473108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian/// id __rw_items[16]; 147433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// id l_collection = (id)collection; 14751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 1476108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian/// objects:__rw_items count:16]; 147710d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// if (limit) { 147810d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// unsigned long startMutations = *enumState.mutationsPtr; 147910d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// do { 148010d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// unsigned long counter = 0; 148110d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// do { 14821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if (startMutations != *enumState.mutationsPtr) 148333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// objc_enumerationMutation(l_collection); 148488f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian/// elem = (type)enumState.itemsPtr[counter++]; 148510d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// stmts; 1486e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian/// __continue_label: ; 148710d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } while (counter < limit); 14881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// } while (limit = [l_collection countByEnumeratingWithState:&enumState 1489108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian/// objects:__rw_items count:16]); 149033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// elem = nil; 1491e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian/// __break_label: ; 149210d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } 149310d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// else 149410d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// elem = nil; 149510d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } 149610d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// 1497b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 1498338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner SourceLocation OrigEnd) { 1499e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); 15001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 1501e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian "ObjCForCollectionStmt Statement stack mismatch"); 15021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(!ObjCBcLabelNo.empty() && 1503e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian "ObjCForCollectionStmt - Label No stack empty"); 15041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 150533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SourceLocation startLoc = S->getLocStart(); 150633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 15075f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef elementName; 150888f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian std::string elementTypeAsString; 150933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian std::string buf; 151033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf = "\n{\n\t"; 151133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) { 151233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // type elem; 15137e24e82a70a2c681f4291a3397bcd1e1005f251aChris Lattner NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl()); 15141ed8e2a39456d064a346a6a5c2f6bd53e6d57345Ted Kremenek QualType ElementType = cast<ValueDecl>(D)->getType(); 1515e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff if (ElementType->isObjCQualifiedIdType() || 1516e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff ElementType->isObjCQualifiedInterfaceType()) 1517e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff // Simply use 'id' for all qualified types. 1518e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff elementTypeAsString = "id"; 1519e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff else 152030c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy()); 152188f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += elementTypeAsString; 152233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += " "; 15234087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar elementName = D->getName(); 152433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 152533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ";\n\t"; 152633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian } 152706767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner else { 152806767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); 15294087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar elementName = DR->getDecl()->getName(); 1530e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff ValueDecl *VD = cast<ValueDecl>(DR->getDecl()); 1531e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff if (VD->getType()->isObjCQualifiedIdType() || 1532e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff VD->getType()->isObjCQualifiedInterfaceType()) 1533e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff // Simply use 'id' for all qualified types. 1534e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff elementTypeAsString = "id"; 1535e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff else 153630c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy()); 153788f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian } 15381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 153933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // struct __objcFastEnumerationState enumState = { 0 }; 154033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; 1541108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian // id __rw_items[16]; 1542108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian buf += "id __rw_items[16];\n\t"; 154333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // id l_collection = (id) 154433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "id l_collection = (id)"; 15457571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian // Find start location of 'collection' the hard way! 15467571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian const char *startCollectionBuf = startBuf; 15477571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf += 3; // skip 'for' 15487571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf = strchr(startCollectionBuf, '('); 15497571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf++; // skip '(' 15507571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian // find 'in' and skip it. 15517571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian while (*startCollectionBuf != ' ' || 15527571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' || 15537571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian (*(startCollectionBuf+3) != ' ' && 15547571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) 15557571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf++; 15567571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf += 3; 15571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Replace: "for (type element in" with string constructed thus far. 1559d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, startCollectionBuf - startBuf, buf); 156033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Replace ')' in for '(' type elem in collection ')' with ';' 15617571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian SourceLocation rightParenLoc = S->getRParenLoc(); 15627571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian const char *rparenBuf = SM->getCharacterData(rightParenLoc); 1563a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf); 156433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf = ";\n\t"; 15651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 156633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 1567108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian // objects:__rw_items count:16]; 156833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // which is synthesized into: 15691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // unsigned int limit = 157033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // ((unsigned int (*) 157133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 15721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // (void *)objc_msgSend)((id)l_collection, 157333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // sel_registerName( 15741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // "countByEnumeratingWithState:objects:count:"), 15751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // (struct __objcFastEnumerationState *)&state, 1576108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian // (id *)__rw_items, (unsigned int)16); 157733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long limit =\n\t\t"; 157833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SynthCountByEnumWithState(buf); 157933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ";\n\t"; 158033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// if (limit) { 158133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// unsigned long startMutations = *enumState.mutationsPtr; 158233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// do { 158333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// unsigned long counter = 0; 158433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// do { 15851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// if (startMutations != *enumState.mutationsPtr) 158633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// objc_enumerationMutation(l_collection); 158788f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian /// elem = (type)enumState.itemsPtr[counter++]; 158833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "if (limit) {\n\t"; 158933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t"; 159033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "do {\n\t\t"; 159133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long counter = 0;\n\t\t"; 159233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "do {\n\t\t\t"; 159333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t"; 159433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "objc_enumerationMutation(l_collection);\n\t\t\t"; 159533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 159688f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += " = ("; 159788f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += elementTypeAsString; 159888f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += ")enumState.itemsPtr[counter++];"; 159933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Replace ')' in for '(' type elem in collection ')' with all of these. 1600d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lparenLoc, 1, buf); 16011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1602e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian /// __continue_label: ; 160333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } while (counter < limit); 16041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// } while (limit = [l_collection countByEnumeratingWithState:&enumState 1605108fb14563f60f895481e2236bfdcea10d1536fbFariborz Jahanian /// objects:__rw_items count:16]); 160633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// elem = nil; 1607e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian /// __break_label: ; 160833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } 160933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// else 161033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// elem = nil; 161133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } 16121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// 1613e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf = ";\n\t"; 1614e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "__continue_label_"; 1615e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += utostr(ObjCBcLabelNo.back()); 1616e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += ": ;"; 1617e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "\n\t\t"; 161833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "} while (counter < limit);\n\t"; 161933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "} while (limit = "; 162033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SynthCountByEnumWithState(buf); 162133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ");\n\t"; 162233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 162365b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += " = (("; 162465b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += elementTypeAsString; 162565b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += ")0);\n\t"; 1626e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "__break_label_"; 1627e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += utostr(ObjCBcLabelNo.back()); 1628e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += ": ;\n\t"; 162933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "}\n\t"; 163033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "else\n\t\t"; 163133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 163265b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += " = (("; 163365b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += elementTypeAsString; 163465b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += ")0);\n\t"; 163533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "}\n"; 16361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 163733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Insert all these *after* the statement body. 1638d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // FIXME: If this should support Obj-C++, support CXXTryStmt 1639600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff if (isa<CompoundStmt>(S->getBody())) { 1640a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1); 1641d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endBodyLoc, buf); 1642600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff } else { 1643600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff /* Need to treat single statements specially. For example: 1644600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * 1645600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * for (A *a in b) if (stuff()) break; 1646600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * for (A *a in b) xxxyy; 1647600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * 1648600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * The following code simply scans ahead to the semi to find the actual end. 1649600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff */ 1650600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff const char *stmtBuf = SM->getCharacterData(OrigEnd); 1651600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff const char *semiBuf = strchr(stmtBuf, ';'); 1652600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff assert(semiBuf && "Can't find ';'"); 1653a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1); 1654d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endBodyLoc, buf); 1655600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff } 1656e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmts.pop_back(); 1657e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian ObjCBcLabelNo.pop_back(); 165833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return 0; 165910d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian} 166010d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian 16611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// RewriteObjCSynchronizedStmt - 1662a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// This routine rewrites @synchronized(expr) stmt; 1663a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// into: 1664a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// objc_sync_enter(expr); 1665a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// @try stmt @finally { objc_sync_exit(expr); } 1666a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// 1667b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 1668a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian // Get the start location and compute the semi location. 1669a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian SourceLocation startLoc = S->getLocStart(); 1670a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 16711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1672a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian assert((*startBuf == '@') && "bogus @synchronized location"); 16731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string buf; 16753498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff buf = "objc_sync_enter((id)"; 16763498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff const char *lparenBuf = startBuf; 16773498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff while (*lparenBuf != '(') lparenBuf++; 1678d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lparenBuf-startBuf+1, buf); 16791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since 16801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // the sync expression is typically a message expression that's already 1681c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff // been rewritten! (which implies the SourceLocation's are invalid). 1682c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff SourceLocation endLoc = S->getSynchBody()->getLocStart(); 1683a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian const char *endBuf = SM->getCharacterData(endLoc); 1684c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff while (*endBuf != ')') endBuf--; 1685a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation rparenLoc = startLoc.getLocWithOffset(endBuf-startBuf); 1686a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf = ");\n"; 1687a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian // declare a new scope with two variables, _stack and _rethrow. 1688a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n"; 1689a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "int buf[18/*32-bit i386*/];\n"; 1690a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "char *pointers[4];} _stack;\n"; 1691a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "id volatile _rethrow = 0;\n"; 1692a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "objc_exception_try_enter(&_stack);\n"; 1693a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 1694d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(rparenLoc, 1, buf); 1695a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian startLoc = S->getSynchBody()->getLocEnd(); 1696a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian startBuf = SM->getCharacterData(startLoc); 16971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1698c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff assert((*startBuf == '}') && "bogus @synchronized block"); 1699a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian SourceLocation lastCurlyLoc = startLoc; 1700a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf = "}\nelse {\n"; 1701a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1702621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff buf += "}\n"; 1703621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff buf += "{ /* implicit finally clause */\n"; 1704a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 1705b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1706b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string syncBuf; 1707b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += " objc_sync_exit("; 17081d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall 17091d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall Expr *syncExpr = S->getSynchExpr(); 17101d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CastKind CK = syncExpr->getType()->isObjCObjectPointerType() 17111d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall ? CK_BitCast : 17121d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall syncExpr->getType()->isBlockPointerType() 17131d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall ? CK_BlockPointerToObjCPointerCast 17141d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall : CK_CPointerToObjCPointerCast; 17151d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 17161d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK, syncExpr); 1717a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string syncExprBufS; 1718a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream syncExprBuf(syncExprBufS); 1719e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner syncExpr->printPretty(syncExprBuf, *Context, 0, 1720e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(LangOpts)); 1721b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += syncExprBuf.str(); 1722b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += ");"; 1723b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1724b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += syncBuf; 1725b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n"; 1726a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "}\n"; 1727a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "}"; 17281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1729d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 1730b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1731b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff bool hasReturns = false; 1732b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(S->getSynchBody(), hasReturns); 1733b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (hasReturns) 1734b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteSyncReturnStmts(S->getSynchBody(), syncBuf); 1735b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1736a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian return 0; 1737a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian} 1738a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian 1739b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S) 1740b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff{ 17418c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff // Perform a bottom up traversal of all children. 17427502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 17438c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff if (*CI) 1744b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff WarnAboutReturnGotoStmts(*CI); 17458c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff 1746b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) { 17471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diags.Report(Context->getFullLoc(S->getLocStart()), 17488c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff TryFinallyContainsReturnDiag); 17498c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff } 17508c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff return; 17518c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff} 17528c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff 1753b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns) 1754b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff{ 1755b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 17567502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 1757b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) 1758b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(*CI, hasReturns); 1759b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1760b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) 1761b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff hasReturns = true; 1762b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1763b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1764b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1765b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::RewriteTryReturnStmts(Stmt *S) { 1766b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 17677502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 1768b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) { 1769b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteTryReturnStmts(*CI); 1770b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1771b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) { 1772b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation startLoc = S->getLocStart(); 1773b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 1774b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1775b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 1776b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'"); 1777a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 1778b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1779b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string buf; 1780b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf = "{ objc_exception_try_exit(&_stack); return"; 1781b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1782d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 6, buf); 1783d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, "}"); 1784b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1785b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1786b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1787b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1788b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) { 1789b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 17907502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 1791b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) { 1792b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteSyncReturnStmts(*CI, syncExitBuf); 1793b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1794b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) { 1795b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation startLoc = S->getLocStart(); 1796b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 1797b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1798b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 1799b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'"); 1800a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation onePastSemiLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 1801b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1802b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string buf; 1803b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf = "{ objc_exception_try_exit(&_stack);"; 1804b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += syncExitBuf; 1805b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += " return"; 1806b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1807d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 6, buf); 1808d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, "}"); 1809b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1810b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1811b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1812b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1813b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { 18147573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Get the start location and compute the semi location. 18157573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation startLoc = S->getLocStart(); 18167573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 18171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18187573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @try location"); 18197573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 18207573098b83e780d1c5bea13b384b610d8f155676Steve Naroff std::string buf; 18217573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // declare a new scope with two variables, _stack and _rethrow. 18227573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "/* @try scope begin */ { struct _objc_exception_data {\n"; 18237573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "int buf[18/*32-bit i386*/];\n"; 18247573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "char *pointers[4];} _stack;\n"; 18257573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "id volatile _rethrow = 0;\n"; 18267573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "objc_exception_try_enter(&_stack);\n"; 182721867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 18287573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 1829d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 4, buf); 18301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18317573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startLoc = S->getTryBody()->getLocEnd(); 18327573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 18337573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 18347573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '}') && "bogus @try block"); 18351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1836c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff SourceLocation lastCurlyLoc = startLoc; 18378f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (S->getNumCatchStmts()) { 1838a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis startLoc = startLoc.getLocWithOffset(1); 1839c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf = " /* @catch begin */ else {\n"; 1840c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " id _caught = objc_exception_extract(&_stack);\n"; 1841c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " objc_exception_try_enter (&_stack);\n"; 1842c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " if (_setjmp(_stack.buf))\n"; 1843c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1844c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " else { /* @catch continue */"; 18451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1846d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, buf); 18478bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff } else { /* no catch list */ 18488bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf = "}\nelse {\n"; 18498bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf += " _rethrow = objc_exception_extract(&_stack);\n"; 18508bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf += "}"; 1851d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 1852c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff } 18537573098b83e780d1c5bea13b384b610d8f155676Steve Naroff Stmt *lastCatchBody = 0; 18548f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { 18558f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor ObjCAtCatchStmt *Catch = S->getCatchStmt(I); 1856c00d8e18ad3d903acfeb5d05163ce90713066a3fDouglas Gregor VarDecl *catchDecl = Catch->getCatchParamDecl(); 18577573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 18588f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (I == 0) 18597573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "if ("; // we are generating code for the first catch clause 18607573098b83e780d1c5bea13b384b610d8f155676Steve Naroff else 18617573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "else if ("; 18628f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor startLoc = Catch->getLocStart(); 18637573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 18641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18657573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @catch location"); 18661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18677573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *lParenLoc = strchr(startBuf, '('); 18687573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 18698f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (Catch->hasEllipsis()) { 1870e12e69223ec279e89ac681023d42184b115e0068Steve Naroff // Now rewrite the body... 18718f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor lastCatchBody = Catch->getCatchBody(); 1872e12e69223ec279e89ac681023d42184b115e0068Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocStart(); 1873e12e69223ec279e89ac681023d42184b115e0068Steve Naroff const char *bodyBuf = SM->getCharacterData(bodyLoc); 18748f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' && 187506767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @catch paren location"); 1876e12e69223ec279e89ac681023d42184b115e0068Steve Naroff assert((*bodyBuf == '{') && "bogus @catch body location"); 18771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1878e12e69223ec279e89ac681023d42184b115e0068Steve Naroff buf += "1) { id _tmp = _caught;"; 1879d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf); 18807ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff } else if (catchDecl) { 18817ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff QualType t = catchDecl->getType(); 1882a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (t == Context->getObjCIdType()) { 18837573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "1) { "; 1884d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 1885506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall } else if (const ObjCObjectPointerType *Ptr = 1886506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall t->getAs<ObjCObjectPointerType>()) { 1887506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall // Should be a pointer to a class. 1888506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface(); 1889506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall if (IDecl) { 189021867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; 1891506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall buf += IDecl->getNameAsString(); 189221867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "\"), (struct objc_object *)_caught)) { "; 1893d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 18947573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 18957573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 18967573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Now rewrite the body... 18978f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor lastCatchBody = Catch->getCatchBody(); 18988f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor SourceLocation rParenLoc = Catch->getRParenLoc(); 18997573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocStart(); 19007573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *bodyBuf = SM->getCharacterData(bodyLoc); 19017573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *rParenBuf = SM->getCharacterData(rParenLoc); 19027573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*rParenBuf == ')') && "bogus @catch paren location"); 19037573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*bodyBuf == '{') && "bogus @catch body location"); 19041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Here we replace ") {" with "= _caught;" (which initializes and 19067573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // declares the @catch parameter). 1907d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;"); 19087ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff } else { 1909b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("@catch rewrite bug"); 19102bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff } 19117573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 19127573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Complete the catch list... 19137573098b83e780d1c5bea13b384b610d8f155676Steve Naroff if (lastCatchBody) { 19147573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocEnd(); 191506767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner assert(*SM->getCharacterData(bodyLoc) == '}' && 191606767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @catch body location"); 19171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1918378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff // Insert the last (implicit) else clause *before* the right curly brace. 1919a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis bodyLoc = bodyLoc.getLocWithOffset(-1); 1920378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf = "} /* last catch end */\n"; 1921378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "else {\n"; 1922378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " _rethrow = _caught;\n"; 1923378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " objc_exception_try_exit(&_stack);\n"; 1924378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "} } /* @catch end */\n"; 1925378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff if (!S->getFinallyStmt()) 1926378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "}\n"; 1927d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(bodyLoc, buf); 19281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19297573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Set lastCurlyLoc 19307573098b83e780d1c5bea13b384b610d8f155676Steve Naroff lastCurlyLoc = lastCatchBody->getLocEnd(); 19317573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 1932a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) { 19337573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startLoc = finalStmt->getLocStart(); 19347573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 19357573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @finally start"); 19361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1937d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 8, "/* @finally */"); 19381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19397573098b83e780d1c5bea13b384b610d8f155676Steve Naroff Stmt *body = finalStmt->getFinallyBody(); 19407573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation startLoc = body->getLocStart(); 19417573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation endLoc = body->getLocEnd(); 194206767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner assert(*SM->getCharacterData(startLoc) == '{' && 194306767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @finally body location"); 19441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(*SM->getCharacterData(endLoc) == '}' && 194506767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @finally body location"); 19461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1947a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis startLoc = startLoc.getLocWithOffset(1); 1948d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n"); 1949a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis endLoc = endLoc.getLocWithOffset(-1); 1950d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n"); 19511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19527573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Set lastCurlyLoc 19537573098b83e780d1c5bea13b384b610d8f155676Steve Naroff lastCurlyLoc = body->getLocEnd(); 19541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19558c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff // Now check for any return/continue/go statements within the @try. 1956b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff WarnAboutReturnGotoStmts(S->getTryBody()); 1957378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff } else { /* no finally clause - make sure we synthesize an implicit one */ 1958378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf = "{ /* implicit finally clause */\n"; 1959378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 1960378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; 1961378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "}"; 1962d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 1963b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1964b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Now check for any return/continue/go statements within the @try. 1965b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // The implicit finally clause won't called if the @try contains any 1966b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // jump statements. 1967b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff bool hasReturns = false; 1968b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(S->getTryBody(), hasReturns); 1969b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (hasReturns) 1970b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteTryReturnStmts(S->getTryBody()); 19717573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 19727573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Now emit the final closing curly brace... 1973a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis lastCurlyLoc = lastCurlyLoc.getLocWithOffset(1); 1974d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(lastCurlyLoc, " } /* @try scope end */\n"); 1975909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian return 0; 1976909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian} 1977909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian 19781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// This can't be done with ReplaceStmt(S, ThrowExpr), since 19791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// the throw expression is typically a message expression that's already 19802bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff// been rewritten! (which implies the SourceLocation's are invalid). 1981b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { 19822bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff // Get the start location and compute the semi location. 19832bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff SourceLocation startLoc = S->getLocStart(); 19842bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff const char *startBuf = SM->getCharacterData(startLoc); 19851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19862bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff assert((*startBuf == '@') && "bogus @throw location"); 19872bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff 19882bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff std::string buf; 19892bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff /* void objc_exception_throw(id) __attribute__((noreturn)); */ 199020ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff if (S->getThrowExpr()) 199120ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff buf = "objc_exception_throw("; 199220ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff else // add an implicit argument 199320ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff buf = "objc_exception_throw(_caught"; 19941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19954ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff // handle "@ throw" correctly. 19964ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff const char *wBuf = strchr(startBuf, 'w'); 19974ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff assert((*wBuf == 'w') && "@throw: can't find 'w'"); 1998d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, wBuf-startBuf+1, buf); 19991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20002bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff const char *semiBuf = strchr(startBuf, ';'); 20012bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff assert((*semiBuf == ';') && "@throw: can't find ';'"); 2002a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf); 2003d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(semiLoc, 1, ");"); 20042bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff return 0; 20052bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff} 2006909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian 2007b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { 200801c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner // Create a new string expression. 200901c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner QualType StrType = Context->getPointerType(Context->CharTy); 201085f9bceab1542aafff012d4d28e998f4ba16e362Anders Carlsson std::string StrEncoding; 20110d504c1da852e58ff802545c823ecff3b6c654b8Daniel Dunbar Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); 201265aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad Expr *Replacement = StringLiteral::Create(*Context, StrEncoding, 20135cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 20145cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StrType, SourceLocation()); 2015dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, Replacement); 20161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20170750618b0beacdc9b0a9e210a661e4746823ced7Chris Lattner // Replace this subexpr in the parent. 2018f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2019e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner return Replacement; 2020311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner} 2021311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner 2022b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { 20231a9376408941d65c285ddad8a0f1a2ac518df344Steve Naroff if (!SelGetUidFunctionDecl) 20241a9376408941d65c285ddad8a0f1a2ac518df344Steve Naroff SynthSelGetUidFunctionDecl(); 2025b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl"); 2026b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff // Create a call to sel_registerName("selName"). 20275f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> SelExprs; 2028b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff QualType argType = Context->getPointerType(Context->CharTy); 20291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SelExprs.push_back(StringLiteral::Create(*Context, 203065aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad Exp->getSelector().getAsString(), 20315cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 20325cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor argType, SourceLocation())); 2033b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 2034b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff &SelExprs[0], SelExprs.size()); 2035dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, SelExp); 2036f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 2037b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff return SelExp; 2038b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff} 2039b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff 2040b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffCallExpr *RewriteObjC::SynthesizeCallToFunctionDecl( 20411d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc, 20421d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc) { 2043ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Get the type, we will need to reference it in a couple spots. 2044934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff QualType msgSendType = FD->getType(); 20451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2046ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Create a reference to the objc_msgSend() declaration. 2047f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExpr *DRE = 2048f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall new (Context) DeclRefExpr(FD, msgSendType, VK_LValue, SourceLocation()); 20491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2050ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Now, we cast the reference to a pointer to the objc_msgSend type. 2051f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner QualType pToFunc = Context->getPointerType(msgSendType); 205288465d3e996e627bbaa11099b039ddab66d5af2cAnders Carlsson ImplicitCastExpr *ICE = 2053a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, 20545baba9d98364a3525d6afa15a04cdad82fd6dd30John McCall DRE, 0, VK_RValue); 20551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2056183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *FT = msgSendType->getAs<FunctionType>(); 20571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20581d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian CallExpr *Exp = 20595291c3cec0dbe8ad1d8e7e67e93af2b1586d5400Douglas Gregor new (Context) CallExpr(*Context, ICE, args, nargs, 2060f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FT->getCallResultType(*Context), 2061f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, EndLoc); 20621d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian return Exp; 2063934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff} 2064934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff 2065d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroffstatic bool scanForProtocolRefs(const char *startBuf, const char *endBuf, 2066d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *&startRef, const char *&endRef) { 2067d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff while (startBuf < endBuf) { 2068d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (*startBuf == '<') 2069d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startRef = startBuf; // mark the start. 2070d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (*startBuf == '>') { 207132174826f58d38c20f376fe64ceac4a278133883Steve Naroff if (startRef && *startRef == '<') { 207232174826f58d38c20f376fe64ceac4a278133883Steve Naroff endRef = startBuf; // mark the end. 207332174826f58d38c20f376fe64ceac4a278133883Steve Naroff return true; 207432174826f58d38c20f376fe64ceac4a278133883Steve Naroff } 207532174826f58d38c20f376fe64ceac4a278133883Steve Naroff return false; 2076d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2077d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startBuf++; 2078d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2079d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff return false; 2080d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff} 2081d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff 208261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanianstatic void scanToNextArgument(const char *&argRef) { 208361477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian int angle = 0; 208461477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian while (*argRef != ')' && (*argRef != ',' || angle > 0)) { 208561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (*argRef == '<') 208661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian angle++; 208761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else if (*argRef == '>') 208861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian angle--; 208961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian argRef++; 209061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 209161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian assert(angle == 0 && "scanToNextArgument - bad protocol type syntax"); 209261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian} 2093291e04b29669d6576e19e35555bbc3cadd2f6649Fariborz Jahanian 2094b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffbool RewriteObjC::needToScanForQualifiers(QualType T) { 209532132a08c0aecc316728d81e1d93726707fde14bFariborz Jahanian if (T->isObjCQualifiedIdType()) 209632132a08c0aecc316728d81e1d93726707fde14bFariborz Jahanian return true; 209784aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (const PointerType *PT = T->getAs<PointerType>()) { 209884aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (PT->getPointeeType()->isObjCQualifiedIdType()) 209984aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return true; 210084aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian } 210184aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (T->isObjCObjectPointerType()) { 210284aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian T = T->getPointeeType(); 210384aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return T->isObjCQualifiedInterfaceType(); 210484aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian } 210524f9cab9288368171caaef4bb18b95e4f6083f22Fariborz Jahanian if (T->isArrayType()) { 210624f9cab9288368171caaef4bb18b95e4f6083f22Fariborz Jahanian QualType ElemTy = Context->getBaseElementType(T); 210724f9cab9288368171caaef4bb18b95e4f6083f22Fariborz Jahanian return needToScanForQualifiers(ElemTy); 210824f9cab9288368171caaef4bb18b95e4f6083f22Fariborz Jahanian } 210984aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return false; 2110d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff} 2111d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff 21124f95b750534f2111f28434b282bcbd5656002816Steve Naroffvoid RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { 21134f95b750534f2111f28434b282bcbd5656002816Steve Naroff QualType Type = E->getType(); 21144f95b750534f2111f28434b282bcbd5656002816Steve Naroff if (needToScanForQualifiers(Type)) { 2115cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff SourceLocation Loc, EndLoc; 21161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2117cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { 2118cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff Loc = ECE->getLParenLoc(); 2119cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff EndLoc = ECE->getRParenLoc(); 2120cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff } else { 2121cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff Loc = E->getLocStart(); 2122cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff EndLoc = E->getLocEnd(); 2123cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff } 2124cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff // This will defend against trying to rewrite synthesized expressions. 2125cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff if (Loc.isInvalid() || EndLoc.isInvalid()) 2126cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff return; 2127cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff 21284f95b750534f2111f28434b282bcbd5656002816Steve Naroff const char *startBuf = SM->getCharacterData(Loc); 2129cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff const char *endBuf = SM->getCharacterData(EndLoc); 21304f95b750534f2111f28434b282bcbd5656002816Steve Naroff const char *startRef = 0, *endRef = 0; 21314f95b750534f2111f28434b282bcbd5656002816Steve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 21324f95b750534f2111f28434b282bcbd5656002816Steve Naroff // Get the locations of the startRef, endRef. 2133a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf); 2134a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1); 21354f95b750534f2111f28434b282bcbd5656002816Steve Naroff // Comment out the protocol references. 2136d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2137d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 21384f95b750534f2111f28434b282bcbd5656002816Steve Naroff } 21394f95b750534f2111f28434b282bcbd5656002816Steve Naroff } 21404f95b750534f2111f28434b282bcbd5656002816Steve Naroff} 21414f95b750534f2111f28434b282bcbd5656002816Steve Naroff 2142b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { 214361477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian SourceLocation Loc; 214461477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian QualType Type; 214572564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *proto = 0; 214661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) { 214761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Loc = VD->getLocation(); 214861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Type = VD->getType(); 214961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 215061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) { 215161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Loc = FD->getLocation(); 215261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // Check for ObjC 'id' and class types that have been adorned with protocol 215361477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // information (id<p>, C<p>*). The protocol references need to be rewritten! 2154183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 215561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian assert(funcType && "missing function type"); 215672564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor proto = dyn_cast<FunctionProtoType>(funcType); 215761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (!proto) 215861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian return; 215961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Type = proto->getResultType(); 216061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 21613d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) { 21623d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff Loc = FD->getLocation(); 21633d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff Type = FD->getType(); 21643d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff } 216561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else 2166e66894c3dea9aeab4403e67bf5baabc20da61cb3Fariborz Jahanian return; 21671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 216861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (needToScanForQualifiers(Type)) { 2169d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Since types are unique, we need to scan the buffer. 21701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2171d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *endBuf = SM->getCharacterData(Loc); 2172d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startBuf = endBuf; 21736cafbf2a678c95d4cdc09ecaa782319bbcf56944Steve Naroff while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) 2174d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startBuf--; // scan backward (from the decl location) for return type. 2175d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startRef = 0, *endRef = 0; 2176d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2177d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Get the locations of the startRef, endRef. 2178a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf); 2179a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1); 2180d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Comment out the protocol references. 2181d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2182d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 2183d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2184d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 218561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (!proto) 218661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian return; // most likely, was a variable 21879165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff // Now check arguments. 218861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian const char *startBuf = SM->getCharacterData(Loc); 218961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian const char *startFuncBuf = startBuf; 21909165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff for (unsigned i = 0; i < proto->getNumArgs(); i++) { 2191d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (needToScanForQualifiers(proto->getArgType(i))) { 2192d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Since types are unique, we need to scan the buffer. 21931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2194d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *endBuf = startBuf; 219561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // scan forward (from the decl location) for argument types. 219661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian scanToNextArgument(endBuf); 2197d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startRef = 0, *endRef = 0; 2198d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2199d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Get the locations of the startRef, endRef. 22001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation LessLoc = 2201a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis Loc.getLocWithOffset(startRef-startFuncBuf); 22021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation GreaterLoc = 2203a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis Loc.getLocWithOffset(endRef-startFuncBuf+1); 2204d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Comment out the protocol references. 2205d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2206d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 2207d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 220861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf = ++endBuf; 220961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 221061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else { 2211aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff // If the function name is derived from a macro expansion, then the 2212aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff // argument buffer will not follow the name. Need to speak with Chris. 2213aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff while (*startBuf && *startBuf != ')' && *startBuf != ',') 221461477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf++; // scan forward (from the decl location) for argument types. 221561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf++; 221661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 22179165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff } 22189165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff} 22199165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff 22204c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanianvoid RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) { 22214c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian QualType QT = ND->getType(); 22224c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const Type* TypePtr = QT->getAs<Type>(); 22234c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (!isa<TypeOfExprType>(TypePtr)) 22244c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian return; 22254c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian while (isa<TypeOfExprType>(TypePtr)) { 22264c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 22274c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 22284c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian TypePtr = QT->getAs<Type>(); 22294c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 22304c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian // FIXME. This will not work for multiple declarators; as in: 22314c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian // __typeof__(a) b,c,d; 223230c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy())); 22334c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 22344c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *startBuf = SM->getCharacterData(DeclLoc); 22354c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (ND->getInit()) { 22364c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian std::string Name(ND->getNameAsString()); 22374c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian TypeAsString += " " + Name + " = "; 22384c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian Expr *E = ND->getInit(); 22394c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation startLoc; 22404c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 22414c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian startLoc = ECE->getLParenLoc(); 22424c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian else 22434c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian startLoc = E->getLocStart(); 2244402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth startLoc = SM->getExpansionLoc(startLoc); 22454c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *endBuf = SM->getCharacterData(startLoc); 2246d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 22474c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 22484c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian else { 22494c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation X = ND->getLocEnd(); 2250402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth X = SM->getExpansionLoc(X); 22514c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *endBuf = SM->getCharacterData(X); 2252d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 22534c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 22544c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian} 22554c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian 2256a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); 2257b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthSelGetUidFunctionDecl() { 2258a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); 22595f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 22600953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2261e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getFuncType = 2262e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size()); 2263ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 22641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2265ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2266a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis SelGetUidIdent, getFuncType, 0, 2267d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2268d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 2269a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian} 2270a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian 2271b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { 227209b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff // declared in <objc/objc.h> 227351efe56116a6283ba707cfb8bf8b4e0b13cb41acDouglas Gregor if (FD->getIdentifier() && 22744087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FD->getName() == "sel_registerName") { 227509b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SelGetUidFunctionDecl = FD; 22769165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff return; 22779165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff } 2278a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCQualifiedInterfaceTypes(FD); 227909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 228009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2281fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbarvoid RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) { 228230c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 228352b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian const char *argPtr = TypeString.c_str(); 228452b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian if (!strchr(argPtr, '^')) { 228552b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian Str += TypeString; 228652b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian return; 228752b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian } 228852b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian while (*argPtr) { 228952b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian Str += (*argPtr == '^' ? '*' : *argPtr); 229052b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian argPtr++; 229152b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian } 229252b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian} 229352b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian 2294e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian// FIXME. Consolidate this routine with RewriteBlockPointerType. 2295fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbarvoid RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str, 2296fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ValueDecl *VD) { 2297e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian QualType Type = VD->getType(); 229830c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 2299e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian const char *argPtr = TypeString.c_str(); 2300e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian int paren = 0; 2301e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian while (*argPtr) { 2302e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian switch (*argPtr) { 2303e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case '(': 2304e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2305e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian paren++; 2306e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2307e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case ')': 2308e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2309e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian paren--; 2310e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2311e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case '^': 2312e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += '*'; 2313e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian if (paren == 1) 2314e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += VD->getNameAsString(); 2315e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2316e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian default: 2317e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2318e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2319e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 2320e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian argPtr++; 2321e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 2322e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian} 2323e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian 2324e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian 2325abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanianvoid RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { 2326abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 2327abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 2328abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType); 2329abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian if (!proto) 2330abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian return; 2331abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian QualType Type = proto->getResultType(); 233230c42404202d2e2512e51efc6066bd614cfdb5a4Douglas Gregor std::string FdStr = Type.getAsString(Context->getPrintingPolicy()); 2333abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += " "; 23344087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar FdStr += FD->getName(); 2335abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += "("; 2336abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian unsigned numArgs = proto->getNumArgs(); 2337abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian for (unsigned i = 0; i < numArgs; i++) { 2338abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian QualType ArgType = proto->getArgType(i); 233952b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian RewriteBlockPointerType(FdStr, ArgType); 2340abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian if (i+1 < numArgs) 2341abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += ", "; 2342abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian } 2343abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += ");\n"; 2344d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, FdStr); 2345abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 2346abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian} 2347abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian 2348c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff// SynthSuperContructorFunctionDecl - id objc_super(id obj, id super); 2349b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthSuperContructorFunctionDecl() { 2350c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff if (SuperContructorFunctionDecl) 2351c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff return; 235246a98a7df016b4a6835a1902c2f8ff2a3a8012baSteve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super"); 23535f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2354c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff QualType argT = Context->getObjCIdType(); 2355c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff assert(!argT.isNull() && "Can't find 'id' type"); 2356c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff ArgTys.push_back(argT); 2357c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff ArgTys.push_back(argT); 2358e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2359e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size()); 2360ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 23611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2362ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2363a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2364d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2365d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 2366c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff} 2367c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff 236809b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); 2369b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendFunctionDecl() { 237009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend"); 23715f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2372a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 237309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff assert(!argT.isNull() && "Can't find 'id' type"); 237409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff ArgTys.push_back(argT); 2375a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 237609b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff assert(!argT.isNull() && "Can't find 'SEL' type"); 237709b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff ArgTys.push_back(argT); 2378e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2379e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2380e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2381ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 23820ed844b04ea4387caa4e1cf3dc375d269657536bChris Lattner SourceLocation(), 2383ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2384a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2385d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2386d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 238709b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 238809b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2389874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...); 2390b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendSuperFunctionDecl() { 2391874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); 23925f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2393465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2394ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 2395df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 2396874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 2397874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 2398874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff ArgTys.push_back(argT); 2399a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 2400874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff assert(!argT.isNull() && "Can't find 'SEL' type"); 2401874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff ArgTys.push_back(argT); 2402e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2403e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2404e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2405ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2407ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2408a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2409d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2410d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 2411874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff} 2412874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff 2413336c8f70ff961c5568de3b9c65fb0502843b7407Fariborz Jahanian// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); 2414b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendStretFunctionDecl() { 241580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret"); 24165f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2417a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 241880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'id' type"); 241980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2420a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 242180a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 242280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2423336c8f70ff961c5568de3b9c65fb0502843b7407Fariborz Jahanian QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2424e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2425e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2426ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2428ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2429a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2430d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2431d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 243280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian} 243380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian 24341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// SynthMsgSendSuperStretFunctionDecl - 2435336c8f70ff961c5568de3b9c65fb0502843b7407Fariborz Jahanian// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...); 2436b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { 24371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump IdentifierInfo *msgSendIdent = 243880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian &Context->Idents.get("objc_msgSendSuper_stret"); 24395f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2440465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2441ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 2442df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 244380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 244480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 244580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2446a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 244780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 244880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2449336c8f70ff961c5568de3b9c65fb0502843b7407Fariborz Jahanian QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 2450e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2451e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2452ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2454ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2455a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2456d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2457d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 245880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian} 245980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian 24601284db8d85782c4eb1d41eb02358613c8681f07fSteve Naroff// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); 2461b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendFpretFunctionDecl() { 2462acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret"); 24635f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2464a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 2465acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian assert(!argT.isNull() && "Can't find 'id' type"); 2466acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian ArgTys.push_back(argT); 2467a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 2468acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 2469acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian ArgTys.push_back(argT); 2470e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, 2471e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size(), 2472e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall true /*isVariadic*/); 2473ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2475ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2476a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 2477d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2478d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 2479acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian} 2480acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian 248109b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff// SynthGetClassFunctionDecl - id objc_getClass(const char *name); 2482b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthGetClassFunctionDecl() { 248309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); 24845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 24850953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2486e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), 2487e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size()); 2488ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2490ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2491a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis getClassIdent, getClassType, 0, 2492d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2493d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 249409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 249509b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2496d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); 2497d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanianvoid RewriteObjC::SynthGetSuperClassFunctionDecl() { 2498d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian IdentifierInfo *getSuperClassIdent = 2499d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian &Context->Idents.get("class_getSuperclass"); 25005f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 2501d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian ArgTys.push_back(Context->getObjCClassType()); 2502e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 2503e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size()); 2504d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 250516573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor SourceLocation(), 2506ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 250716573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor getSuperClassIdent, 250816573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor getClassType, 0, 2509d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2510d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, 251116573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor false); 2512d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian} 2513d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian 251497bbab2df74cbfe221fb20454738d607a41f3ca4Fariborz Jahanian// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name); 2515b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthGetMetaClassFunctionDecl() { 25169bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); 25175f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 16> ArgTys; 25180953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2519e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType getClassType = getSimpleFunctionType(Context->getObjCIdType(), 2520e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall &ArgTys[0], ArgTys.size()); 2521ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2523ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 2524a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis getClassIdent, getClassType, 0, 2525d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, 2526d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_None, false); 25279bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff} 25289bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff 2529b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { 2530d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff QualType strType = getConstantStringStructType(); 2531d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 2532d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff std::string S = "__NSConstantStringImpl_"; 25337691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff 25347691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff std::string tmpName = InFileName; 25357691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff unsigned i; 25367691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff for (i=0; i < tmpName.length(); i++) { 25377691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff char c = tmpName.at(i); 25387691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff // replace any non alphanumeric characters with '_'. 25397691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff if (!isalpha(c) && (c < '0' || c > '9')) 25407691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff tmpName[i] = '_'; 25417691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff } 25427691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff S += tmpName; 25437691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff S += "_"; 2544d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff S += utostr(NumObjCStringLiterals++); 2545d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 2546ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "static __NSConstantStringImpl " + S; 2547ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,"; 2548ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "0x000007c8,"; // utf8_str 2549d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // The pretty printer for StringLiteral handles escape characters properly. 2550a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string prettyBufS; 2551a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream prettyBuf(prettyBufS); 2552e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner Exp->getString()->printPretty(prettyBuf, *Context, 0, 2553e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(LangOpts)); 2554ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += prettyBuf.str(); 2555ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += ","; 2556fd5b76fe99a123630321b45667a78f1a15be7241Steve Naroff Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; 25571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 25581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 2559ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), &Context->Idents.get(S), 2560ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara strType, 0, SC_Static, SC_None); 2561f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, VK_LValue, 2562f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 25632de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, 25641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Context->getPointerType(DRE->getType()), 2565f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 2566f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 25679698464266660346fa2da1bddc3e6404a9819b25Steve Naroff // cast to NSConstantString * 25689d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), 25691d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK_CPointerToObjCPointerCast, Unop); 2570dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, cast); 2571f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 25729698464266660346fa2da1bddc3e6404a9819b25Steve Naroff return cast; 2573beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff} 2574beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff 2575874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff// struct objc_super { struct objc_object *receiver; struct objc_class *super; }; 2576b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffQualType RewriteObjC::getSuperStructType() { 2577874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff if (!SuperStructDecl) { 2578465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2579ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 2580df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 2581874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType FieldTypes[2]; 25821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2583874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // struct objc_object *receiver; 25841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[0] = Context->getObjCIdType(); 2585874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // struct objc_class *super; 25861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[1] = Context->getObjCClassType(); 258744b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2588874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // Create fields 258944b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor for (unsigned i = 0; i < 2; ++i) { 25901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, 2591ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 25921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 0, 2593a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis FieldTypes[i], 0, 2594a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis /*BitWidth=*/0, 25957a614d8380297fcd2bc23986241905d97222948cRichard Smith /*Mutable=*/false, 25967a614d8380297fcd2bc23986241905d97222948cRichard Smith /*HasInit=*/false)); 259744b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor } 25981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2599838db383b69b9fb55f55c8e9546477df198a4faaDouglas Gregor SuperStructDecl->completeDefinition(); 2600874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } 2601874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff return Context->getTagDeclType(SuperStructDecl); 2602874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff} 2603874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff 2604b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffQualType RewriteObjC::getConstantStringStructType() { 2605d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff if (!ConstantStringDecl) { 2606465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 2607ba877adeb49ed6dc17f27fa3a3bcd0cca713fd68Abramo Bagnara SourceLocation(), SourceLocation(), 2608df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("__NSConstantStringImpl")); 2609d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff QualType FieldTypes[4]; 26101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2611d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // struct objc_object *receiver; 26121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[0] = Context->getObjCIdType(); 2613d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // int flags; 26141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[1] = Context->IntTy; 2615d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // char *str; 26161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[2] = Context->getPointerType(Context->CharTy); 2617d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // long length; 26181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[3] = Context->LongTy; 261944b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2620d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // Create fields 262144b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor for (unsigned i = 0; i < 4; ++i) { 26221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConstantStringDecl->addDecl(FieldDecl::Create(*Context, 26231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConstantStringDecl, 2624ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), 262544b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor SourceLocation(), 0, 2626a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis FieldTypes[i], 0, 262744b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor /*BitWidth=*/0, 26287a614d8380297fcd2bc23986241905d97222948cRichard Smith /*Mutable=*/true, 26297a614d8380297fcd2bc23986241905d97222948cRichard Smith /*HasInit=*/false)); 263044b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor } 263144b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2632838db383b69b9fb55f55c8e9546477df198a4faaDouglas Gregor ConstantStringDecl->completeDefinition(); 2633d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff } 2634d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff return Context->getTagDeclType(ConstantStringDecl); 2635d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff} 2636d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 26371d35b168348a308696d1fce29a18c14143f61d6aFariborz JahanianStmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 26381d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation StartLoc, 26391d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc) { 2640a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian if (!SelGetUidFunctionDecl) 2641a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian SynthSelGetUidFunctionDecl(); 264209b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff if (!MsgSendFunctionDecl) 264309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SynthMsgSendFunctionDecl(); 2644874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff if (!MsgSendSuperFunctionDecl) 2645874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff SynthMsgSendSuperFunctionDecl(); 264680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (!MsgSendStretFunctionDecl) 264780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SynthMsgSendStretFunctionDecl(); 264880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (!MsgSendSuperStretFunctionDecl) 264980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SynthMsgSendSuperStretFunctionDecl(); 2650acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian if (!MsgSendFpretFunctionDecl) 2651acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian SynthMsgSendFpretFunctionDecl(); 265209b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff if (!GetClassFunctionDecl) 265309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SynthGetClassFunctionDecl(); 2654d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian if (!GetSuperClassFunctionDecl) 2655d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian SynthGetSuperClassFunctionDecl(); 26569bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff if (!GetMetaClassFunctionDecl) 26579bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff SynthGetMetaClassFunctionDecl(); 26581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2659874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // default to objc_msgSend(). 266080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 266180a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // May need to use objc_msgSend_stret() as well. 266280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendStretFlavor = 0; 2663621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { 2664621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QualType resultType = mDecl->getResultType(); 2665fb87b89fc9eb103e19fb8e4b925c23f0bd091b99Douglas Gregor if (resultType->isRecordType()) 266680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian MsgSendStretFlavor = MsgSendStretFunctionDecl; 26678b51fd76319d8b71f401cc6ad56e6f4f7be77958Chris Lattner else if (resultType->isRealFloatingType()) 2668acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian MsgSendFlavor = MsgSendFpretFunctionDecl; 266980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian } 26701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2671934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Synthesize a call to objc_msgSend(). 26725f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> MsgExprs; 267304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor switch (Exp->getReceiverKind()) { 267404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::SuperClass: { 267504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendFlavor = MsgSendSuperFunctionDecl; 267604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (MsgSendStretFlavor) 267704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 267804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 267904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 268004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 268104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 26825f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 4> InitExprs; 268304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 268404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // set the receiver to self, the first argument to all methods. 268504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 268604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2687a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 268804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 2689f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Context->getObjCIdType(), 2690f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, 2691f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation())) 269204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ); // set the 'receiver'. 269304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 269404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 26955f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> ClsExprs; 269604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 269704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 269865aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad ClassDecl->getIdentifier()->getName(), 26995cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 27005cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor argType, SourceLocation())); 270104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, 270204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 270304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 270404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, 270504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor EndLoc); 270604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (Class)objc_getClass("CurrentClass") 270704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 270804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCClassType(), 270997bbab2df74cbfe221fb20454738d607a41f3ca4Fariborz Jahanian CK_BitCast, Cls); 271004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.clear(); 271104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(ArgExpr); 271204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 271304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], ClsExprs.size(), 271404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 271504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 271604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 271704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // To turn off a warning, type-cast to 'id' 271804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( // set 'super class', using class_getSuperclass(). 271904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, 272004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCIdType(), 2721a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, Cls)); 272204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super 272304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType superType = getSuperStructType(); 272404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *SuperRep; 272504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 272662ec1f2fd7368542bb926c04797fb07023547694Francois Pichet if (LangOpts.MicrosoftExt) { 272704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SynthSuperContructorFunctionDecl(); 272804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Simulate a contructor call... 272904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, 2730f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, 2731f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 273204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], 273304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.size(), 2734f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, 2735f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 273604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // The code for super is a little tricky to prevent collision with 273704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // the structure definition in the header. The rewriter has it's own 273804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // internal definition (__rw_objc_super) that is uses. This is why 273904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // we need the cast below. For example: 274004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 274104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // 27422de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 274304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 2744f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 2745f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 274604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = NoTypeInfoCStyleCastExpr(Context, 274704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(superType), 2748a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, SuperRep); 27499bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff } else { 275004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super) { <exprs from above> } 275104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitListExpr *ILE = 275204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) InitListExpr(*Context, SourceLocation(), 275304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &InitExprs[0], InitExprs.size(), 275404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 275504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor TypeSourceInfo *superTInfo 275604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor = Context->getTrivialTypeSourceInfo(superType); 275704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 2758f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, 2759f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall ILE, false); 276004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super * 27612de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 276204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 2763f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 2764f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 27659bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff } 276604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(SuperRep); 276704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 276804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 276904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 277004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::Class: { 27715f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> ClsExprs; 277204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 277304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *Class 2774506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface(); 277504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor IdentifierInfo *clsName = Class->getIdentifier(); 277604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 277765aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad clsName->getName(), 27785cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 27793e2193ce5feb2feb092e5ae615e85148e06e9fd2Anders Carlsson argType, SourceLocation())); 278004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 278104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 278204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 278304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 278404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(Cls); 278504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 278604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 278704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 278804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::SuperInstance:{ 278904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendFlavor = MsgSendSuperFunctionDecl; 279004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (MsgSendStretFlavor) 279104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 279204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 279304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 27945f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 4> InitExprs; 279504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 279604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 279704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2798a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 279904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 2800f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall Context->getObjCIdType(), 2801f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, SourceLocation())) 280204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ); // set the 'receiver'. 280304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 280404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 28055f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> ClsExprs; 280604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 280704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 280865aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad ClassDecl->getIdentifier()->getName(), 28095cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, argType, 28105cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor SourceLocation())); 281104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 281204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 281304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 281404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 281504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (Class)objc_getClass("CurrentClass") 281604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 281704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCClassType(), 2818a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, Cls); 281904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.clear(); 282004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(ArgExpr); 282104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 282204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], ClsExprs.size(), 282304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 282404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 282504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 282604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // To turn off a warning, type-cast to 'id' 282704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 282804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // set 'super class', using class_getSuperclass(). 282904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2830a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, Cls)); 283104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super 283204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType superType = getSuperStructType(); 283304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *SuperRep; 283404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 283562ec1f2fd7368542bb926c04797fb07023547694Francois Pichet if (LangOpts.MicrosoftExt) { 283604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SynthSuperContructorFunctionDecl(); 283704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Simulate a contructor call... 283804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, 2839f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, 2840f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 284104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], 284204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.size(), 2843f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_LValue, SourceLocation()); 284404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // The code for super is a little tricky to prevent collision with 284504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // the structure definition in the header. The rewriter has it's own 284604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // internal definition (__rw_objc_super) that is uses. This is why 284704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // we need the cast below. For example: 284804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 284904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // 28502de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 285104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 2852f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, 285304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 285404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = NoTypeInfoCStyleCastExpr(Context, 285504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(superType), 2856a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, SuperRep); 2857874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } else { 285804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super) { <exprs from above> } 285904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitListExpr *ILE = 286004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) InitListExpr(*Context, SourceLocation(), 286104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &InitExprs[0], InitExprs.size(), 286204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 286304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor TypeSourceInfo *superTInfo 286404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor = Context->getTrivialTypeSourceInfo(superType); 286504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 2866f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall superType, VK_RValue, ILE, 2867f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall false); 2868874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } 286904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(SuperRep); 287004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 28716568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff } 287204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 287304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::Instance: { 287404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Remove all type-casts because it may contain objc-style types; e.g. 287504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Foo<Proto> *. 287604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *recExpr = Exp->getInstanceReceiver(); 287704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) 287804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor recExpr = CE->getSubExpr(); 2879baac1ea9e06985fceff856398655c6dfdab8c85cFariborz Jahanian CastKind CK = recExpr->getType()->isObjCObjectPointerType() 2880baac1ea9e06985fceff856398655c6dfdab8c85cFariborz Jahanian ? CK_BitCast : recExpr->getType()->isBlockPointerType() 2881baac1ea9e06985fceff856398655c6dfdab8c85cFariborz Jahanian ? CK_BlockPointerToObjCPointerCast 2882baac1ea9e06985fceff856398655c6dfdab8c85cFariborz Jahanian : CK_CPointerToObjCPointerCast; 2883baac1ea9e06985fceff856398655c6dfdab8c85cFariborz Jahanian 288404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 2885baac1ea9e06985fceff856398655c6dfdab8c85cFariborz Jahanian CK, recExpr); 288604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(recExpr); 288704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 288804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 288904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 289004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 2891beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff // Create a call to sel_registerName("selName"), it will be the 2nd argument. 28925f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<Expr*, 8> SelExprs; 2893934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff QualType argType = Context->getPointerType(Context->CharTy); 28941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SelExprs.push_back(StringLiteral::Create(*Context, 289565aa6885818d4b4eea2e5a9d12085b2398148662Jay Foad Exp->getSelector().getAsString(), 28965cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor StringLiteral::Ascii, false, 28975cee1195584fa8672253139c86e922daeda69b9eDouglas Gregor argType, SourceLocation())); 2898934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 28991d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian &SelExprs[0], SelExprs.size(), 29001d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian StartLoc, 29011d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian EndLoc); 2902934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff MsgExprs.push_back(SelExp); 29031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2904934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Now push any user supplied arguments. 2905934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff for (unsigned i = 0; i < Exp->getNumArgs(); i++) { 29066568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff Expr *userExpr = Exp->getArg(i); 29077e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff // Make all implicit casts explicit...ICE comes in handy:-) 29087e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { 29097e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff // Reuse the ICE type, it is exactly what the doctor ordered. 2910dff3f018e0bf93a08f135954a5771bfe664a7744Fariborz Jahanian QualType type = ICE->getType(); 2911dff3f018e0bf93a08f135954a5771bfe664a7744Fariborz Jahanian if (needToScanForQualifiers(type)) 2912dff3f018e0bf93a08f135954a5771bfe664a7744Fariborz Jahanian type = Context->getObjCIdType(); 29131f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // Make sure we convert "type (^)(...)" to "type (*)(...)". 29144fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(type); 29151a38b46ae2f818592577546c8c800ada8de7962bFariborz Jahanian const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 29161d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CastKind CK; 29171d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall if (SubExpr->getType()->isIntegralType(*Context) && 29181d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall type->isBooleanType()) { 29191d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_IntegralToBoolean; 29201d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else if (type->isObjCObjectPointerType()) { 29211d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall if (SubExpr->getType()->isBlockPointerType()) { 29221d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BlockPointerToObjCPointerCast; 29231d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else if (SubExpr->getType()->isPointerType()) { 29241d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_CPointerToObjCPointerCast; 29251d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else { 29261d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BitCast; 29271d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } 29281d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else { 29291d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BitCast; 29301d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } 29311d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall 29321d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); 2933d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian } 2934d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian // Make id<P...> cast into an 'id' cast. 29356eec8e883de118b431e3ead5b1e604a6ac68ff6bDouglas Gregor else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { 2936a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (CE->getType()->isObjCQualifiedIdType()) { 29376eec8e883de118b431e3ead5b1e604a6ac68ff6bDouglas Gregor while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) 2938d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian userExpr = CE->getSubExpr(); 29391d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CastKind CK; 29401d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall if (userExpr->getType()->isIntegralType(*Context)) { 29411d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_IntegralToPointer; 29421d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else if (userExpr->getType()->isBlockPointerType()) { 29431d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BlockPointerToObjCPointerCast; 29441d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else if (userExpr->getType()->isPointerType()) { 29451d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_CPointerToObjCPointerCast; 29461d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } else { 29471d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK = CK_BitCast; 29481d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall } 29499d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 29501d9b3b25f7ac0d0195bba6b507a684fe5e7943eeJohn McCall CK, userExpr); 2951d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian } 29521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 29536568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff MsgExprs.push_back(userExpr); 2954621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // We've transferred the ownership to MsgExprs. For now, we *don't* null 2955621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // out the argument in the original expression (since we aren't deleting 2956f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info. 2957621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff //Exp->setArg(i, 0); 2958934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff } 2959ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Generate the funky cast. 2960ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff CastExpr *cast; 29615f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<QualType, 8> ArgTypes; 2962ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff QualType returnType; 29631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2964ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Push 'id' and 'SEL', the 2 implicit arguments. 2965c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff if (MsgSendFlavor == MsgSendSuperFunctionDecl) 2966c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff ArgTypes.push_back(Context->getPointerType(getSuperStructType())); 2967c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff else 2968a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ArgTypes.push_back(Context->getObjCIdType()); 2969a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ArgTypes.push_back(Context->getObjCSelType()); 297089951a86b594513c2a013532ed45d197413b1087Chris Lattner if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { 2971ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Push any user argument types. 297289951a86b594513c2a013532ed45d197413b1087Chris Lattner for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 297389951a86b594513c2a013532ed45d197413b1087Chris Lattner E = OMD->param_end(); PI != E; ++PI) { 297489951a86b594513c2a013532ed45d197413b1087Chris Lattner QualType t = (*PI)->getType()->isObjCQualifiedIdType() 29751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ? Context->getObjCIdType() 297689951a86b594513c2a013532ed45d197413b1087Chris Lattner : (*PI)->getType(); 2977a206b0614a392cfef19aaaa894f9d3c756006421Steve Naroff // Make sure we convert "t (^)(...)" to "t (*)(...)". 29784fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(t); 2979352336bb0a480b044eb03e7359e73d3b173d9cddSteve Naroff ArgTypes.push_back(t); 2980352336bb0a480b044eb03e7359e73d3b173d9cddSteve Naroff } 29813a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian returnType = Exp->getType(); 29823a448fb539f66b204a6119946973d29fa5547574Fariborz Jahanian convertToUnqualifiedObjCType(returnType); 29834fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(returnType); 2984ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff } else { 2985a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek returnType = Context->getObjCIdType(); 2986ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff } 2987ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Get the type, we will need to reference it in a couple spots. 2988874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType msgSendType = MsgSendFlavor->getType(); 29891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2990ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Create a reference to the objc_msgSend() declaration. 29911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, 2992f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_LValue, SourceLocation()); 2993ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff 29941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 2995ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // If we don't do this cast, we get the following bizarre warning/note: 2996ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // xx.m:13: warning: function called through a non-compatible type 2997ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // xx.m:13: note: if this code is reached, the program will abort 29989d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast = NoTypeInfoCStyleCastExpr(Context, 29999d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Context->getPointerType(Context->VoidTy), 3000a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, DRE); 30011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3002ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Now do the "normal" pointer to function cast. 3003e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall QualType castType = 3004e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 3005e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall // If we don't have a method decl, force a variadic cast. 3006e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true); 3007ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff castType = Context->getPointerType(castType); 3008a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 30099d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast); 3010ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff 3011ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Don't forget the parens to enforce the proper binding. 30121d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 30131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3014183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *FT = msgSendType->getAs<FunctionType>(); 3015668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 30161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MsgExprs.size(), 3017f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FT->getResultType(), VK_RValue, 3018f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall EndLoc); 301933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian Stmt *ReplacingStmt = CE; 302080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (MsgSendStretFlavor) { 302180a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // We have the method which returns a struct/union. Must also generate 302280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // call to objc_msgSend_stret and hang both varieties on a conditional 302380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // expression which dictate which one to envoke depending on size of 302480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // method's return type. 30251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 302680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Create a reference to the objc_msgSend_stret() declaration. 30271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType, 3028f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_LValue, SourceLocation()); 302980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Need to cast objc_msgSend_stret to "void *" (see above comment). 30309d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast = NoTypeInfoCStyleCastExpr(Context, 30319d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Context->getPointerType(Context->VoidTy), 3032a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, STDRE); 303380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Now do the "normal" pointer to function cast. 3034e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 3035e23cf437fe76b1ed02d63c3f61b456fd48a915f5John McCall Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false); 303680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian castType = Context->getPointerType(castType); 3037a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 30389d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast); 30391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 304080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Don't forget the parens to enforce the proper binding. 30418189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); 30421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3043183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall FT = msgSendType->getAs<FunctionType>(); 3044668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 30451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MsgExprs.size(), 3046f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall FT->getResultType(), VK_RValue, 3047f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 30481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 304980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Build sizeof(returnType) 3050f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne UnaryExprOrTypeTraitExpr *sizeofExpr = 3051f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf, 3052f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne Context->getTrivialTypeSourceInfo(returnType), 3053f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne Context->getSizeType(), SourceLocation(), 3054f4e3cfbe8abd124be6341ef5d714819b4fbd9082Peter Collingbourne SourceLocation()); 305580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 305680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. 305780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // For X86 it is more complicated and some kind of target specific routine 305880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // is needed to decide what to do. 30591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump unsigned IntSize = 306098be4943e8dc4f3905629a7102668960873cf863Chris Lattner static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 30619996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis IntegerLiteral *limit = IntegerLiteral::Create(*Context, 30629996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis llvm::APInt(IntSize, 8), 30639996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis Context->IntTy, 30649996a7f06a3c5b4554692e7177930cf4e8ef09afArgyrios Kyrtzidis SourceLocation()); 3065f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall BinaryOperator *lessThanExpr = 3066f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, 3067f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, SourceLocation()); 306880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 30691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConditionalOperator *CondExpr = 307047e1f7c68bf375cac470fdb2b599ddbb395aeb52Douglas Gregor new (Context) ConditionalOperator(lessThanExpr, 307147e1f7c68bf375cac470fdb2b599ddbb395aeb52Douglas Gregor SourceLocation(), CE, 307256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall SourceLocation(), STCE, 30730943168ac126b8047f30f6bd215fbe7db14d61baJohn McCall returnType, VK_RValue, OK_Ordinary); 3074f9b949fecf339a2c9bd97dd11a272c4878f85ce4Fariborz Jahanian ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 3075f9b949fecf339a2c9bd97dd11a272c4878f85ce4Fariborz Jahanian CondExpr); 307680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian } 3077f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 307833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return ReplacingStmt; 307933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian} 308033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian 3081b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { 30821d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(), 30831d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Exp->getLocEnd()); 30841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3085934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Now do the actual rewrite. 3086dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, ReplacingStmt); 30871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3088f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 308933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return ReplacingStmt; 3090ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff} 3091ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff 3092621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// typedef struct objc_object Protocol; 3093621edce9cd7d4e06979daf911cc306350619f33bSteve NaroffQualType RewriteObjC::getProtocolType() { 3094621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!ProtocolTypeDecl) { 3095a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall TypeSourceInfo *TInfo 3096a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); 3097621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, 3098344577e6b58f42d18dc8118c8903b49a85dc005eAbramo Bagnara SourceLocation(), SourceLocation(), 3099621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff &Context->Idents.get("Protocol"), 3100a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall TInfo); 3101621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3102621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return Context->getTypeDeclType(ProtocolTypeDecl); 3103621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff} 3104621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 310536ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian/// RewriteObjCProtocolExpr - Rewrite a protocol expression into 3106621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// a synthesized/forward data reference (to the protocol's metadata). 3107621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// The forward references (and metadata) are generated in 3108621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// RewriteObjC::HandleTranslationUnit(). 3109b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { 3110621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); 3111621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff IdentifierInfo *ID = &Context->Idents.get(Name); 31121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 3113ff676cb48fe8bf7be2feaa251dc7c5fb15af4730Abramo Bagnara SourceLocation(), ID, getProtocolType(), 0, 3114d931b086984257de68868a64a235c2b4b34003fbJohn McCall SC_Extern, SC_None); 3115f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), VK_LValue, 3116f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall SourceLocation()); 31172de56d1d0c3a504ad1529de2677628bdfbb95cd4John McCall Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, 3118621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getPointerType(DRE->getType()), 3119f89e55ab1bfb3ea997f8b02997c611a02254eb2dJohn McCall VK_RValue, OK_Ordinary, SourceLocation()); 31209d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), 3121a5bbc50b1e1b27008a79c11a6c6c33e51d8a9cc9John McCall CK_BitCast, 31229d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall DerefExpr); 3123621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ReplaceStmt(Exp, castExpr); 31243fc73ee0c613715ebce78e30b4d050ea715a007dDouglas Gregor ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl()); 3125f2ad2c92720f0e25c032188783a1d6374155f03aFariborz Jahanian // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 3126621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return castExpr; 31271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 312836ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian} 312936ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian 31301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, 3131baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff const char *endBuf) { 3132baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff while (startBuf < endBuf) { 3133baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (*startBuf == '#') { 3134baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // Skip whitespace. 3135baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf) 3136baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff ; 3137baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (!strncmp(startBuf, "if", strlen("if")) || 3138baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "ifdef", strlen("ifdef")) || 3139baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "ifndef", strlen("ifndef")) || 3140baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "define", strlen("define")) || 3141baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "undef", strlen("undef")) || 3142baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "else", strlen("else")) || 3143baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "elif", strlen("elif")) || 3144baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "endif", strlen("endif")) || 3145baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "pragma", strlen("pragma")) || 3146baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "include", strlen("include")) || 3147baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "import", strlen("import")) || 3148baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "include_next", strlen("include_next"))) 3149baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff return true; 3150baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3151baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff startBuf++; 3152baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3153baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff return false; 3154baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff} 3155baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff 31565845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanian/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to 315726e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian/// an objective-c class with ivars. 31585845717880d1b0ecaf68c58093681eb18ace9237Fariborz Jahanianvoid RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 315926e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result) { 3160a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); 31614087f27e5416c799bcb6be072f905be752acb61cDaniel Dunbar assert(CDecl->getName() != "" && 31622e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor "Name missing in SynthesizeObjCInternalStruct"); 3163212b768a4b39479bc8cce1268a95a1adbd825542Fariborz Jahanian // Do not synthesize more than once. 3164a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (ObjCSynthesizedStructs.count(CDecl)) 3165212b768a4b39479bc8cce1268a95a1adbd825542Fariborz Jahanian return; 3166a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); 3167f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner int NumIvars = CDecl->ivar_size(); 31682c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian SourceLocation LocStart = CDecl->getLocStart(); 316905c272fed899b8d3142cf080e86a235fc6168862Douglas Gregor SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc(); 31701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 31712c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 31722c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 31731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3174aff56d0bffdad7ed75db938d5e61e1ce3d5cd195Fariborz Jahanian // If no ivars and no root or if its root, directly or indirectly, 3175f1de0ca05e2df6f23bd559028693a12d1ebdaaf6Fariborz Jahanian // have no ivars (thus not synthesized) then no need to synthesize this class. 31767723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) && 3177f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { 31782c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 3179d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, Result); 318026e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian return; 31812c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian } 31821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 31831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME: This has potential of causing problem. If 3184a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek // SynthesizeObjCInternalStruct is ever called recursively. 3185fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result += "\nstruct "; 3186d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 318762ec1f2fd7368542bb926c04797fb07023547694Francois Pichet if (LangOpts.MicrosoftExt) 318861ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff Result += "_IMPL"; 318905b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff 3190fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian if (NumIvars > 0) { 3191fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff const char *cursor = strchr(startBuf, '{'); 31921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert((cursor && endBuf) 3193a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek && "SynthesizeObjCInternalStruct - malformed @interface"); 3194baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // If the buffer contains preprocessor directives, we do more fine-grained 3195baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrites. This is intended to fix code that looks like (which occurs in 3196baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // NSURL.h, for example): 3197baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // 3198baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #ifdef XYZ 3199baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @interface Foo : NSObject 3200baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #else 3201baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @interface FooBar : NSObject 3202baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #endif 3203baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // { 3204baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // int i; 3205baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // } 3206baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @end 3207baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // 3208baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // This clause is segregated to avoid breaking the common case. 3209baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (BufferContainsPPDirectives(startBuf, cursor)) { 32101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() : 32111711fc91efb36d131f7ba771f73f0154dc1abd1fArgyrios Kyrtzidis CDecl->getAtStartLoc(); 3212baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff const char *endHeader = SM->getCharacterData(L); 32132c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts); 3214baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff 3215cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl->protocol_begin() != CDecl->protocol_end()) { 3216baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // advance to the end of the referenced protocols. 3217baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff while (endHeader < cursor && *endHeader != '>') endHeader++; 3218baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff endHeader++; 3219baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3220baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrite the original header 3221d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endHeader-startBuf, Result); 3222baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } else { 3223baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrite the original header *without* disturbing the '{' 3224d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, cursor-startBuf, Result); 3225baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3226a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 3227fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result = "\n struct "; 3228d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 322939bbd9f5918950436821585afc6244b1fe2c7295Steve Naroff Result += "_IMPL "; 3230d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 3231819173c41e395744480e8f325dc5c02438420604Steve Naroff Result += "_IVARS;\n"; 32321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3233fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // insert the super class structure definition. 3234f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner SourceLocation OnePastCurly = 3235a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis LocStart.getLocWithOffset(cursor-startBuf+1); 3236d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(OnePastCurly, Result); 3237fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff } 3238fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff cursor++; // past '{' 32391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3240fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // Now comment out any visibility specifiers. 3241fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff while (cursor < endBuf) { 3242fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff if (*cursor == '@') { 3243a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3244df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner // Skip whitespace. 3245df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor) 3246df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner /*scan*/; 3247df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner 3248fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian // FIXME: presence of @public, etc. inside comment results in 3249fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian // this transformation as well, which is still correct c-code. 3250fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff if (!strncmp(cursor, "public", strlen("public")) || 3251fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff !strncmp(cursor, "private", strlen("private")) || 3252c5e327712499caa2a9f3b6591490de8cb7df0b5bSteve Naroff !strncmp(cursor, "package", strlen("package")) || 32539567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian !strncmp(cursor, "protected", strlen("protected"))) 3254d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, "// "); 3255fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian } 32569567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // FIXME: If there are cases where '<' is used in ivar declaration part 32579567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // of user code, then scan the ivar list and use needToScanForQualifiers 32589567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // for type checking. 32599567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian else if (*cursor == '<') { 3260a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3261d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, "/* "); 32629567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian cursor = strchr(cursor, '>'); 32639567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian cursor++; 3264a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis atLoc = LocStart.getLocWithOffset(cursor-startBuf); 3265d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, " */"); 3266ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff } else if (*cursor == '^') { // rewrite block specifier. 3267a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis SourceLocation caretLoc = LocStart.getLocWithOffset(cursor-startBuf); 3268d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(caretLoc, 1, "*"); 32699567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian } 3270fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff cursor++; 3271fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian } 3272fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // Don't forget to add a ';'!! 3273a64ccefdf0ea4e03ec88805d71b0af74950c7472Argyrios Kyrtzidis InsertText(LocEnd.getLocWithOffset(1), ";"); 3274fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff } else { // we don't have any instance variables - insert super struct. 32752c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 3276fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result += " {\n struct "; 3277d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 327839bbd9f5918950436821585afc6244b1fe2c7295Steve Naroff Result += "_IMPL "; 3279d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 3280819173c41e395744480e8f325dc5c02438420604Steve Naroff Result += "_IVARS;\n};\n"; 3281d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, Result); 328226e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian } 328326e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian // Mark this struct as having been generated. 3284a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (!ObjCSynthesizedStructs.insert(CDecl)) 3285b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct"); 328626e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian} 328726e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian 3288d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian//===----------------------------------------------------------------------===// 3289d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// Meta Data Emission 3290d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian//===----------------------------------------------------------------------===// 32911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3293d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// RewriteImplementations - This routine rewrites all method implementations 3294d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// and emits meta-data. 32951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3296d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::RewriteImplementations() { 3297d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int ClsDefCount = ClassImplementation.size(); 3298d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int CatDefCount = CategoryImplementation.size(); 32991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3300d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Rewrite implemented methods 3301d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (int i = 0; i < ClsDefCount; i++) 3302d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteImplementationDecl(ClassImplementation[i]); 3303ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner 3304d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (int i = 0; i < CatDefCount; i++) 3305d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteImplementationDecl(CategoryImplementation[i]); 33062e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian} 33072e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3308d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::RewriteByRefString(std::string &ResultStr, 3309d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const std::string &Name, 3310d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ValueDecl *VD, bool def) { 3311d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(BlockByRefDeclNo.count(VD) && 3312d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "RewriteByRefString: ByRef decl missing"); 3313d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (def) 3314d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ResultStr += "struct "; 3315d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ResultStr += "__Block_byref_" + Name + 3316d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "_" + utostr(BlockByRefDeclNo[VD]) ; 3317d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 3318621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3319d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianstatic bool HasLocalVariableExternalStorage(ValueDecl *VD) { 3320d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 3321d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage()); 3322d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return false; 3323d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 33241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3325d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianstd::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, 3326d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef funcName, 3327d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Tag) { 3328d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const FunctionType *AFT = CE->getFunctionType(); 3329d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType RT = AFT->getResultType(); 3330d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string StructRef = "struct " + Tag; 3331d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" + 3332d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian funcName.str() + "_" + "block_func_" + utostr(i); 33331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3334d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDecl *BD = CE->getBlockDecl(); 33351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3336d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isa<FunctionNoProtoType>(AFT)) { 3337d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // No user-supplied arguments. Still need to pass in a pointer to the 3338d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // block (to reference imported block decl refs). 3339d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "(" + StructRef + " *__cself)"; 3340d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else if (BD->param_empty()) { 3341d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "(" + StructRef + " *__cself)"; 3342d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 3343d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); 3344d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(FT && "SynthesizeBlockFunc: No function proto"); 3345d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += '('; 3346d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // first add the implicit argument. 3347d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += StructRef + " *__cself, "; 3348d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string ParamStr; 3349d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (BlockDecl::param_iterator AI = BD->param_begin(), 3350d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BD->param_end(); AI != E; ++AI) { 3351d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (AI != BD->param_begin()) S += ", "; 3352d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ParamStr = (*AI)->getNameAsString(); 3353d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType QT = (*AI)->getType(); 3354d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (convertBlockPointerToFunctionPointer(QT)) 3355d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); 3356621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3357d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); 3358d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ParamStr; 33599d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 3360d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (FT->isVariadic()) { 3361d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!BD->param_empty()) S += ", "; 3362d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "..."; 3363d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3364d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ')'; 3365621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3366d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " {\n"; 33671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3368d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Create local declarations to avoid rewriting all closure decl ref exprs. 3369d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // First, emit a declaration for all "by ref" decls. 3370d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 3371d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BlockByRefDecls.end(); I != E; ++I) { 3372d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " "; 3373d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Name = (*I)->getNameAsString(); 3374d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string TypeString; 3375d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefString(TypeString, Name, (*I)); 3376d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian TypeString += " *"; 3377d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Name = TypeString + Name; 3378d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; 3379d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3380d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Next, emit a declaration for all "by copy" declarations. 3381d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 3382d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BlockByCopyDecls.end(); I != E; ++I) { 3383d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " "; 3384d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Handle nested closure invocation. For example: 3385d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 3386d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // void (^myImportedClosure)(void); 3387d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // myImportedClosure = ^(void) { setGlobalInt(x + y); }; 3388d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 3389d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // void (^anotherClosure)(void); 3390d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // anotherClosure = ^(void) { 3391d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // myImportedClosure(); // import and invoke the closure 3392d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // }; 3393d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 3394d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType((*I)->getType())) { 3395d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerTypeVariable(S, (*I)); 3396d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " = ("; 3397d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerType(S, (*I)->getType()); 3398d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ")"; 3399d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n"; 3400d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3401d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else { 3402d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Name = (*I)->getNameAsString(); 3403d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType QT = (*I)->getType(); 3404d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasLocalVariableExternalStorage(*I)) 3405d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT = Context->getPointerType(QT); 3406d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 3407d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += Name + " = __cself->" + 3408d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian (*I)->getNameAsString() + "; // bound by copy\n"; 3409e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 3410621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3411d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string RewrittenStr = RewrittenBlockExprs[CE]; 3412d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *cstr = RewrittenStr.c_str(); 3413d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (*cstr++ != '{') ; 3414d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += cstr; 3415d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "\n"; 3416d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return S; 3417d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 3418621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3419d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianstd::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 3420d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef funcName, 3421d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Tag) { 3422d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string StructRef = "struct " + Tag; 3423d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string S = "static void __"; 34241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3425d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += funcName; 3426d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "_block_copy_" + utostr(i); 3427d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "(" + StructRef; 3428d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "*dst, " + StructRef; 3429d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "*src) {"; 3430d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 3431d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = ImportedBlockDecls.end(); I != E; ++I) { 3432d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ValueDecl *VD = (*I); 3433d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "_Block_object_assign((void*)&dst->"; 3434d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += (*I)->getNameAsString(); 3435d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", (void*)src->"; 3436d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += (*I)->getNameAsString(); 3437d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockByRefDeclsPtrSet.count((*I))) 3438d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 3439d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (VD->getType()->isBlockPointerType()) 3440d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 3441d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3442d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 34439d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 3444d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "}\n"; 3445d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3446d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "\nstatic void __"; 3447d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += funcName; 3448d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "_block_dispose_" + utostr(i); 3449d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "(" + StructRef; 3450d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "*src) {"; 3451d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 3452d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = ImportedBlockDecls.end(); I != E; ++I) { 3453d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ValueDecl *VD = (*I); 3454d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "_Block_object_dispose((void*)src->"; 3455d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += (*I)->getNameAsString(); 3456d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockByRefDeclsPtrSet.count((*I))) 3457d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 3458d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (VD->getType()->isBlockPointerType()) 3459d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 3460d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3461d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 3462621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3463d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "}\n"; 3464d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return S; 3465621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff} 3466621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3467d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianstd::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 3468d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Desc) { 3469d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string S = "\nstruct " + Tag; 3470d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Constructor = " " + Tag; 34711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3472d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " {\n struct __block_impl impl;\n"; 3473d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " struct " + Desc; 3474d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "* Desc;\n"; 3475621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3476d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += "(void *fp, "; // Invoke function pointer. 3477d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += "struct " + Desc; // Descriptor pointer. 3478d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " *desc"; 34791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3480d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefs.size()) { 3481d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output all "by copy" declarations. 3482d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 3483d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BlockByCopyDecls.end(); I != E; ++I) { 3484d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " "; 3485d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string FieldName = (*I)->getNameAsString(); 3486d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string ArgName = "_" + FieldName; 3487d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Handle nested closure invocation. For example: 3488d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 3489d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // void (^myImportedBlock)(void); 3490d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 3491d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 3492d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // void (^anotherBlock)(void); 3493d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // anotherBlock = ^(void) { 3494d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // myImportedBlock(); // import and invoke the closure 3495d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // }; 3496d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 3497d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType((*I)->getType())) { 3498d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "struct __block_impl *"; 3499d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += ", void *" + ArgName; 3500d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 3501d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType QT = (*I)->getType(); 3502d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasLocalVariableExternalStorage(*I)) 3503d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT = Context->getPointerType(QT); 3504d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT.getAsStringInternal(FieldName, Context->getPrintingPolicy()); 3505d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT.getAsStringInternal(ArgName, Context->getPrintingPolicy()); 3506d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += ", " + ArgName; 3507d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3508d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += FieldName + ";\n"; 3509d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3510d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output all "by ref" declarations. 3511d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 3512d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BlockByRefDecls.end(); I != E; ++I) { 3513d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " "; 3514d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string FieldName = (*I)->getNameAsString(); 3515d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string ArgName = "_" + FieldName; 3516d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian { 3517d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string TypeString; 3518d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefString(TypeString, FieldName, (*I)); 3519d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian TypeString += " *"; 3520d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FieldName = TypeString + FieldName; 3521d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ArgName = TypeString + ArgName; 3522d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += ", " + ArgName; 3523d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3524d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += FieldName + "; // by ref\n"; 3525d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3526d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Finish writing the constructor. 3527d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += ", int flags=0)"; 3528d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Initialize all "by copy" arguments. 3529d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool firsTime = true; 3530d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 3531d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BlockByCopyDecls.end(); I != E; ++I) { 3532d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Name = (*I)->getNameAsString(); 3533d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (firsTime) { 3534d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " : "; 3535d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian firsTime = false; 3536d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3537d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3538d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += ", "; 3539d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType((*I)->getType())) 3540d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += Name + "((struct __block_impl *)_" + Name + ")"; 3541d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3542d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += Name + "(_" + Name + ")"; 3543d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3544d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Initialize all "by ref" arguments. 3545d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 3546d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BlockByRefDecls.end(); I != E; ++I) { 3547d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Name = (*I)->getNameAsString(); 3548d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (firsTime) { 3549d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " : "; 3550d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian firsTime = false; 3551d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3552d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3553d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += ", "; 3554d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += Name + "(_" + Name + "->__forwarding)"; 3555d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3556d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3557d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " {\n"; 3558d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (GlobalVarDecl) 3559d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 3560d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3561d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 3562d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 35631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3564d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " Desc = desc;\n"; 3565d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 3566d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Finish writing the constructor. 3567d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += ", int flags=0) {\n"; 3568d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (GlobalVarDecl) 3569d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 3570d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3571d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 3572d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 3573d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " Desc = desc;\n"; 35749d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 3575d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += " "; 3576d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Constructor += "}\n"; 3577d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += Constructor; 3578d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "};\n"; 3579d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return S; 35802e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian} 35812e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3582d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianstd::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, 3583d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string ImplTag, int i, 3584d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef FunName, 3585d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned hasCopy) { 3586d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string S = "\nstatic struct " + DescTag; 3587d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3588d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " {\n unsigned long reserved;\n"; 3589d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " unsigned long Block_size;\n"; 3590d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (hasCopy) { 3591d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " void (*copy)(struct "; 3592d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ImplTag; S += "*, struct "; 3593d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ImplTag; S += "*);\n"; 3594d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3595d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " void (*dispose)(struct "; 3596d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ImplTag; S += "*);\n"; 3597d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3598d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "} "; 3599621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3600d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += DescTag + "_DATA = { 0, sizeof(struct "; 3601d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ImplTag + ")"; 3602d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (hasCopy) { 3603d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", __" + FunName.str() + "_block_copy_" + utostr(i); 3604d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", __" + FunName.str() + "_block_dispose_" + utostr(i); 3605d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3606d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "};\n"; 3607d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return S; 3608d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 3609653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor 3610d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, 3611d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef FunName) { 3612d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Insert declaration for the function in which block literal is used. 3613d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CurFunctionDeclToDeclareForBlock && !Blocks.empty()) 3614d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 3615d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool RewriteSC = (GlobalVarDecl && 3616d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian !Blocks.empty() && 3617d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GlobalVarDecl->getStorageClass() == SC_Static && 3618d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GlobalVarDecl->getType().getCVRQualifiers()); 3619d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (RewriteSC) { 3620d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string SC(" void __"); 3621d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SC += GlobalVarDecl->getNameAsString(); 3622d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SC += "() {}"; 3623d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(FunLocStart, SC); 3624653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor } 3625d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3626d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Insert closures that were part of the function. 3627d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (unsigned i = 0, count=0; i < Blocks.size(); i++) { 3628d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CollectBlockDeclRefInfo(Blocks[i]); 3629d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Need to copy-in the inner copied-in variables not actually used in this 3630d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // block. 3631d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (int j = 0; j < InnerDeclRefsCount[i]; j++) { 3632d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefExpr *Exp = InnerDeclRefs[count++]; 3633d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ValueDecl *VD = Exp->getDecl(); 3634d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs.push_back(Exp); 3635d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) { 3636d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByCopyDeclsPtrSet.insert(VD); 3637d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByCopyDecls.push_back(VD); 3638d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3639d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) { 3640d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDeclsPtrSet.insert(VD); 3641d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDecls.push_back(VD); 3642d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3643d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // imported objects in the inner blocks not used in the outer 3644d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // blocks must be copied/disposed in the outer block as well. 3645d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Exp->isByRef() || 3646d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VD->getType()->isObjCObjectPointerType() || 3647d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VD->getType()->isBlockPointerType()) 3648d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedBlockDecls.insert(VD); 3649d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 36501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3651d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i); 3652d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i); 36531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3654d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); 36551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3656d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(FunLocStart, CI); 36571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3658d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); 36591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3660d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(FunLocStart, CF); 36612e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3662d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ImportedBlockDecls.size()) { 3663d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); 3664d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(FunLocStart, HF); 3665d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3666d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, 3667d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedBlockDecls.size() > 0); 3668d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(FunLocStart, BD); 3669d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3670d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs.clear(); 3671d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDecls.clear(); 3672d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDeclsPtrSet.clear(); 3673d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByCopyDecls.clear(); 3674d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByCopyDeclsPtrSet.clear(); 3675d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedBlockDecls.clear(); 3676d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3677d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (RewriteSC) { 3678d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Must insert any 'const/volatile/static here. Since it has been 3679d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // removed as result of rewriting of block literals. 3680d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string SC; 3681d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (GlobalVarDecl->getStorageClass() == SC_Static) 3682d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SC = "static "; 3683d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (GlobalVarDecl->getType().isConstQualified()) 3684d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SC += "const "; 3685d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (GlobalVarDecl->getType().isVolatileQualified()) 3686d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SC += "volatile "; 3687d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (GlobalVarDecl->getType().isRestrictQualified()) 3688d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SC += "restrict "; 3689d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(FunLocStart, SC); 36908f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff } 3691d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3692d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Blocks.clear(); 3693d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerDeclRefsCount.clear(); 3694d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerDeclRefs.clear(); 3695d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewrittenBlockExprs.clear(); 369626e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian} 369726e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian 3698d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { 3699d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 3700d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef FuncName = FD->getName(); 37012e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3702d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SynthesizeBlockLiterals(FunLocStart, FuncName); 3703d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 37041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3705d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianstatic void BuildUniqueMethodName(std::string &Name, 3706d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCMethodDecl *MD) { 3707d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCInterfaceDecl *IFace = MD->getClassInterface(); 3708d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Name = IFace->getName(); 3709d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Name += "__" + MD->getSelector().getAsString(); 3710d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Convert colons to underscores. 3711d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string::size_type loc = 0; 3712d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while ((loc = Name.find(":", loc)) != std::string::npos) 3713d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Name.replace(loc, 1, "_"); 3714d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 37151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3716d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { 3717d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); 3718d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian //SourceLocation FunLocStart = MD->getLocStart(); 3719d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation FunLocStart = MD->getLocStart(); 3720d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string FuncName; 3721d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BuildUniqueMethodName(FuncName, MD); 3722d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SynthesizeBlockLiterals(FunLocStart, FuncName); 3723d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 37241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3725d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::GetBlockDeclRefExprs(Stmt *S) { 3726d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (Stmt::child_range CI = S->children(); CI; ++CI) 3727d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (*CI) { 3728d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) 3729d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GetBlockDeclRefExprs(CBE->getBody()); 3730d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3731d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GetBlockDeclRefExprs(*CI); 3732d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3733d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Handle specific things. 3734d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) { 3735d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME: Handle enums. 3736d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!isa<FunctionDecl>(CDRE->getDecl())) 3737d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs.push_back(CDRE); 3738d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3739d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) 3740d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasLocalVariableExternalStorage(DRE->getDecl())) { 3741d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefExpr *BDRE = 3742d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian new (Context)BlockDeclRefExpr(cast<VarDecl>(DRE->getDecl()), 3743d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DRE->getType(), 3744d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VK_LValue, DRE->getLocation(), false); 3745d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs.push_back(BDRE); 37462e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian } 3747d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3748d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 3749d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 37502e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3751d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, 3752d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs, 3753d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) { 3754d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (Stmt::child_range CI = S->children(); CI; ++CI) 3755d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (*CI) { 3756d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) { 3757d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl())); 3758d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GetInnerBlockDeclRefExprs(CBE->getBody(), 3759d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerBlockDeclRefs, 3760d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerContexts); 3761d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3762d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 3763d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GetInnerBlockDeclRefExprs(*CI, 3764d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerBlockDeclRefs, 3765d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerContexts); 37661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3767ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3768d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Handle specific things. 3769d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) { 3770d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!isa<FunctionDecl>(CDRE->getDecl()) && 3771d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian !InnerContexts.count(CDRE->getDecl()->getDeclContext())) 3772d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerBlockDeclRefs.push_back(CDRE); 3773d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3774d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 3775d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) 3776d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Var->isFunctionOrMethodVarDecl()) 3777d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedLocalExternalDecls.insert(Var); 3778d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3779d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3780d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 3781d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 37821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3783d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// convertFunctionTypeOfBlocks - This routine converts a function type 3784d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// whose result type may be a block pointer or whose argument type(s) 3785d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// might be block pointers to an equivalent function type replacing 3786d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// all block pointers to function pointers. 3787d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz JahanianQualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { 3788d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 3789d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FTP will be null for closures that don't take arguments. 3790d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Generate a funky cast. 3791d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<QualType, 8> ArgTypes; 3792d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType Res = FT->getResultType(); 3793d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool HasBlockType = convertBlockPointerToFunctionPointer(Res); 3794d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3795d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (FTP) { 3796d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 3797d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = FTP->arg_type_end(); I && (I != E); ++I) { 3798d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType t = *I; 3799d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Make sure we convert "t (^)(...)" to "t (*)(...)". 3800d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (convertBlockPointerToFunctionPointer(t)) 3801d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian HasBlockType = true; 3802d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ArgTypes.push_back(t); 3803d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 38042e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian } 3805d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType FuncType; 3806d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME. Does this work if block takes no argument but has a return type 3807d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // which is of block type? 3808d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasBlockType) 3809d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size()); 3810d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else FuncType = QualType(FT, 0); 3811d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return FuncType; 3812d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 38131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3814d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz JahanianStmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 3815d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Navigate to relevant type information. 3816d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const BlockPointerType *CPT = 0; 3817653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor 3818d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { 3819d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CPT = DRE->getType()->getAs<BlockPointerType>(); 3820d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else if (const BlockDeclRefExpr *CDRE = 3821d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian dyn_cast<BlockDeclRefExpr>(BlockExp)) { 3822d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CPT = CDRE->getType()->getAs<BlockPointerType>(); 3823d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { 3824d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CPT = MExpr->getType()->getAs<BlockPointerType>(); 3825d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3826d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) { 3827d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return SynthesizeBlockCall(Exp, PRE->getSubExpr()); 3828653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor } 3829d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 3830d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CPT = IEXPR->getType()->getAs<BlockPointerType>(); 3831d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (const ConditionalOperator *CEXPR = 3832d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian dyn_cast<ConditionalOperator>(BlockExp)) { 3833d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *LHSExp = CEXPR->getLHS(); 3834d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp); 3835d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *RHSExp = CEXPR->getRHS(); 3836d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); 3837d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *CONDExp = CEXPR->getCond(); 3838d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ConditionalOperator *CondExpr = 3839d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian new (Context) ConditionalOperator(CONDExp, 3840d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), cast<Expr>(LHSStmt), 3841d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), cast<Expr>(RHSStmt), 3842d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp->getType(), VK_RValue, OK_Ordinary); 3843d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return CondExpr; 3844d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { 3845d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CPT = IRE->getType()->getAs<BlockPointerType>(); 3846d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else if (const PseudoObjectExpr *POE 3847d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian = dyn_cast<PseudoObjectExpr>(BlockExp)) { 3848d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CPT = POE->getType()->castAs<BlockPointerType>(); 3849d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 3850d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(1 && "RewriteBlockClass: Bad type"); 3851d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3852d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(CPT && "RewriteBlockClass: Bad type"); 3853d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); 3854d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(FT && "RewriteBlockClass: Bad type"); 3855d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 3856d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FTP will be null for closures that don't take arguments. 38571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3858d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 3859d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), SourceLocation(), 3860d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian &Context->Idents.get("__block_impl")); 3861d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); 38621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3863d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Generate a funky cast. 3864d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<QualType, 8> ArgTypes; 38651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3866d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Push the block argument type. 3867d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ArgTypes.push_back(PtrBlock); 3868d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (FTP) { 3869d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 3870d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = FTP->arg_type_end(); I && (I != E); ++I) { 3871d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType t = *I; 3872d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Make sure we convert "t (^)(...)" to "t (*)(...)". 3873d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!convertBlockPointerToFunctionPointer(t)) 3874d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian convertToUnqualifiedObjCType(t); 3875d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ArgTypes.push_back(t); 3876d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 38779f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian } 3878d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Now do the pointer to function cast. 3879d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType PtrToFuncCastType 3880d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size()); 38811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3882d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); 38831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3884d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock, 3885d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CK_BitCast, 3886d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const_cast<Expr*>(BlockExp)); 3887d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Don't forget the parens to enforce the proper binding. 3888d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 3889d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlkCast); 3890d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian //PE->dump(); 3891ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian 3892d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 3893d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), 3894d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian &Context->Idents.get("FuncPtr"), 3895d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->VoidPtrTy, 0, 3896d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /*BitWidth=*/0, /*Mutable=*/true, 3897d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /*HasInit=*/false); 3898d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 3899d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD->getType(), VK_LValue, 3900d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OK_Ordinary); 39011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3902d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3903d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, 3904d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CK_BitCast, ME); 3905d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); 3906d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3907d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<Expr*, 8> BlkExprs; 3908d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Add the implicit argument. 3909d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlkExprs.push_back(BlkCast); 3910d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Add the user arguments. 3911d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (CallExpr::arg_iterator I = Exp->arg_begin(), 3912d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = Exp->arg_end(); I != E; ++I) { 3913d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlkExprs.push_back(*I); 3914ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3915d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0], 3916d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlkExprs.size(), 3917d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp->getType(), VK_RValue, 3918d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 3919d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return CE; 39209f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian} 3921f4d331dd922f92478ebf30e808c0ca97ce49418bFariborz Jahanian 3922d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// We need to return the rewritten expression to handle cases where the 3923d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// BlockDeclRefExpr is embedded in another expression being rewritten. 3924d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// For example: 3925d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// 3926d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// int main() { 3927d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// __block Foo *f; 3928d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// __block int i; 3929d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// 3930d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// void (^myblock)() = ^() { 3931d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten). 3932d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// i = 77; 3933d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// }; 3934d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian//} 3935d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz JahanianStmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) { 3936d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 3937d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // for each DeclRefExp where BYREFVAR is name of the variable. 3938d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ValueDecl *VD; 3939d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool isArrow = true; 3940d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp)) 3941d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VD = BDRE->getDecl(); 3942d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else { 3943d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VD = cast<DeclRefExpr>(DeclRefExp)->getDecl(); 3944d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian isArrow = false; 3945d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 3946d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3947d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 3948d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), 3949d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian &Context->Idents.get("__forwarding"), 3950d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->VoidPtrTy, 0, 3951d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /*BitWidth=*/0, /*Mutable=*/true, 3952d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /*HasInit=*/false); 3953d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow, 3954d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD, SourceLocation(), 3955d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD->getType(), VK_LValue, 3956d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OK_Ordinary); 39571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3958d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef Name = VD->getName(); 3959d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 3960d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian &Context->Idents.get(Name), 3961d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->VoidPtrTy, 0, 3962d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /*BitWidth=*/0, /*Mutable=*/true, 3963d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /*HasInit=*/false); 3964d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(), 3965d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclRefExp->getType(), VK_LValue, OK_Ordinary); 39667c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 3967d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3968d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 3969d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Need parens to enforce precedence. 3970d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 3971d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclRefExp->getExprLoc(), 3972d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ME); 3973d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceStmt(DeclRefExp, PE); 3974d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return PE; 3975d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 39761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3977d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// Rewrites the imported local variable V with external storage 3978d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// (static, extern, etc.) as *V 3979d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// 3980d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz JahanianStmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { 3981d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ValueDecl *VD = DRE->getDecl(); 3982d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 3983d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!ImportedLocalExternalDecls.count(Var)) 3984d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return DRE; 3985d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), 3986d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VK_LValue, OK_Ordinary, 3987d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DRE->getLocation()); 3988d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Need parens to enforce precedence. 3989d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 3990d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp); 3991d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceStmt(DRE, PE); 3992d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return PE; 3993d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 3994621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3995d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { 3996d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation LocStart = CE->getLParenLoc(); 3997d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation LocEnd = CE->getRParenLoc(); 39981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3999d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Need to avoid trying to rewrite synthesized casts. 4000d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (LocStart.isInvalid()) 4001d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 4002d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Need to avoid trying to rewrite casts contained in macros. 4003d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) 4004d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 40051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4006d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 4007d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 4008d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType QT = CE->getType(); 4009d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const Type* TypePtr = QT->getAs<Type>(); 4010d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isa<TypeOfExprType>(TypePtr)) { 4011d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 4012d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 4013d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string TypeAsString = "("; 4014d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerType(TypeAsString, QT); 4015d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian TypeAsString += ")"; 4016d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); 4017d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 4018ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4019d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // advance the location to startArgList. 4020d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *argPtr = startBuf; 40211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4022d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (*argPtr++ && (argPtr < endBuf)) { 4023d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian switch (*argPtr) { 4024d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case '^': 4025d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Replace the '^' with '*'. 4026d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian LocStart = LocStart.getLocWithOffset(argPtr-startBuf); 4027d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceText(LocStart, 1, "*"); 4028d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 4029d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4030ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 4031d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 4032d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 40331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4034d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { 4035d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation DeclLoc = FD->getLocation(); 4036d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned parenCount = 0; 40371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4038d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // We have 1 or more arguments that have closure pointers. 4039d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *startBuf = SM->getCharacterData(DeclLoc); 4040d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *startArgList = strchr(startBuf, '('); 40411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4042d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); 40431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4044d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian parenCount++; 4045d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // advance the location to startArgList. 4046d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf); 4047d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert((DeclLoc.isValid()) && "Invalid DeclLoc"); 40484f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff 4049d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *argPtr = startArgList; 4050d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4051d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (*argPtr++ && parenCount) { 4052d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian switch (*argPtr) { 4053d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case '^': 4054d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Replace the '^' with '*'. 4055d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList); 4056d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceText(DeclLoc, 1, "*"); 4057d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 4058d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case '(': 4059d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian parenCount++; 4060d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 4061d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case ')': 4062d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian parenCount--; 4063d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 4064621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 40654f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff } 4066d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 4067545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian} 4068311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner 4069d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianbool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { 4070d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const FunctionProtoType *FTP; 4071d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const PointerType *PT = QT->getAs<PointerType>(); 4072d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PT) { 4073d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 4074d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 4075d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 4076d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 4077d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 4078d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4079d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (FTP) { 4080d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 4081d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = FTP->arg_type_end(); I != E; ++I) 4082d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType(*I)) 4083d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return true; 4084d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 40856cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return false; 40866cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian} 40876cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 4088d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianbool RewriteObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) { 4089d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const FunctionProtoType *FTP; 4090d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const PointerType *PT = QT->getAs<PointerType>(); 4091d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PT) { 4092d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 409354055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 4094d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 4095d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 4096d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 40971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 4098d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (FTP) { 4099d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 4100d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = FTP->arg_type_end(); I != E; ++I) { 4101d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if ((*I)->isObjCQualifiedIdType()) 4102d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return true; 4103d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if ((*I)->isObjCObjectPointerType() && 4104d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian (*I)->getPointeeType()->isObjCQualifiedInterfaceType()) 4105d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return true; 4106e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 4107d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 410854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4109d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return false; 411054055232a5ddb9529726e934301b125cb720a273Steve Naroff} 411154055232a5ddb9529726e934301b125cb720a273Steve Naroff 4112d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen, 4113d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *&RParen) { 4114d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *argPtr = strchr(Name, '('); 4115d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); 41161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4117d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian LParen = argPtr; // output the start. 4118d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian argPtr++; // skip past the left paren. 4119d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned parenCount = 1; 4120d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4121d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (*argPtr && parenCount) { 4122d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian switch (*argPtr) { 4123d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case '(': parenCount++; break; 4124d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case ')': parenCount--; break; 4125d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian default: break; 4126d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4127d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (parenCount) argPtr++; 412854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4129d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert((*argPtr == ')') && "Rewriter fuzzy parser confused"); 4130d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RParen = argPtr; // output the end 413154055232a5ddb9529726e934301b125cb720a273Steve Naroff} 4132ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis 4133d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { 4134d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 4135d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerFunctionArgs(FD); 4136d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 4137d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4138d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Handle Variables and Typedefs. 4139d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation DeclLoc = ND->getLocation(); 4140d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType DeclT; 4141d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VarDecl *VD = dyn_cast<VarDecl>(ND)) 4142d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclT = VD->getType(); 4143d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND)) 4144d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclT = TDD->getUnderlyingType(); 4145d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) 4146d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclT = FD->getType(); 4147d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 4148d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled"); 4149d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4150d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *startBuf = SM->getCharacterData(DeclLoc); 4151d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *endBuf = startBuf; 4152d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // scan backward (from the decl location) for the end of the previous decl. 4153d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) 4154d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian startBuf--; 4155d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf); 4156d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string buf; 4157d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned OrigLength=0; 4158d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // *startBuf != '^' if we are dealing with a pointer to function that 4159d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // may take block argument types (which will be handled below). 4160d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (*startBuf == '^') { 4161d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Replace the '^' with '*', computing a negative offset. 4162d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf = '*'; 4163d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian startBuf++; 4164d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OrigLength++; 4165d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4166d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (*startBuf != ')') { 4167d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += *startBuf; 4168d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian startBuf++; 4169d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OrigLength++; 4170d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4171d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += ')'; 4172d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OrigLength++; 4173d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4174d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PointerTypeTakesAnyBlockArguments(DeclT) || 4175d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PointerTypeTakesAnyObjCQualifiedType(DeclT)) { 4176d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Replace the '^' with '*' for arguments. 4177d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Replace id<P> with id/*<>*/ 4178d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclLoc = ND->getLocation(); 4179d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian startBuf = SM->getCharacterData(DeclLoc); 4180d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *argListBegin, *argListEnd; 4181d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GetExtentOfArgList(startBuf, argListBegin, argListEnd); 4182d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (argListBegin < argListEnd) { 4183d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (*argListBegin == '^') 4184d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += '*'; 4185d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (*argListBegin == '<') { 4186d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += "/*"; 4187d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += *argListBegin++; 4188d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OrigLength++;; 4189d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (*argListBegin != '>') { 4190d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += *argListBegin++; 4191d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OrigLength++; 419220432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian } 4193d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += *argListBegin; 4194d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += "*/"; 419520432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian } 419620432ef377e8ebcf2933d3f568eaf72766b06116Fariborz Jahanian else 4197d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += *argListBegin; 4198d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian argListBegin++; 4199d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OrigLength++; 420054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4201d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian buf += ')'; 4202d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OrigLength++; 420354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4204d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceText(Start, OrigLength, buf); 4205d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4206d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 420754055232a5ddb9529726e934301b125cb720a273Steve Naroff} 420839ba4aeca296b1c9f04bde7d9d3cbbf129f1abd3Argyrios Kyrtzidis 420901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 4210d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: 4211d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, 4212d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// struct Block_byref_id_object *src) { 4213d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// _Block_object_assign (&_dest->object, _src->object, 4214d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 4215d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // object 4216d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// _Block_object_assign(&_dest->object, _src->object, 4217d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 4218d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // block 4219d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// } 4220d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// And: 4221d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { 4222d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// _Block_object_dispose(_src->object, 4223d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 4224d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // object 4225d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// _Block_object_dispose(_src->object, 4226d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 4227d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // block 4228d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// } 4229d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4230d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianstd::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, 4231d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int flag) { 4232d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string S; 4233d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CopyDestroyCache.count(flag)) 4234d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return S; 4235d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CopyDestroyCache.insert(flag); 4236d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S = "static void __Block_byref_id_object_copy_"; 4237d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += utostr(flag); 4238d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "(void *dst, void *src) {\n"; 4239d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4240d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // offset into the object pointer is computed as: 4241d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // void * + void* + int + int + void* + void * 4242d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned IntSize = 4243d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 4244d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned VoidPtrSize = 4245d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); 4246d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4247d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth(); 4248d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " _Block_object_assign((char*)dst + "; 4249d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += utostr(offset); 4250d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ", *(void * *) ((char*)src + "; 4251d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += utostr(offset); 4252d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "), "; 4253d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += utostr(flag); 4254d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ");\n}\n"; 4255d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4256d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "static void __Block_byref_id_object_dispose_"; 4257d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += utostr(flag); 4258d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "(void *src) {\n"; 4259d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += " _Block_object_dispose(*(void * *) ((char*)src + "; 4260d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += utostr(offset); 4261d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += "), "; 4262d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += utostr(flag); 4263d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian S += ");\n}\n"; 426401aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff return S; 426501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff} 426601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 4267d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// RewriteByRefVar - For each __block typex ND variable this routine transforms 4268d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// the declaration into: 4269d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// struct __Block_byref_ND { 4270d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// void *__isa; // NULL for everything except __weak pointers 4271d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// struct __Block_byref_ND *__forwarding; 4272d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// int32_t __flags; 4273d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// int32_t __size; 4274d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object 4275d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object 4276d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// typex ND; 4277d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// }; 4278d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// 4279d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// It then replaces declaration of ND variable with: 4280d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 4281d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// __size=sizeof(struct __Block_byref_ND), 4282d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// ND=initializer-if-any}; 4283d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// 4284d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// 4285d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::RewriteByRefVar(VarDecl *ND) { 4286d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Insert declaration for the function in which block literal is 4287d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // used. 4288d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CurFunctionDeclToDeclareForBlock) 4289d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 4290d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int flag = 0; 4291d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int isa = 0; 4292d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 4293d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (DeclLoc.isInvalid()) 4294d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // If type location is missing, it is because of missing type (a warning). 4295d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Use variable's location which is good for this case. 4296d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclLoc = ND->getLocation(); 4297d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *startBuf = SM->getCharacterData(DeclLoc); 4298d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation X = ND->getLocEnd(); 4299d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian X = SM->getExpansionLoc(X); 4300d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *endBuf = SM->getCharacterData(X); 4301d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Name(ND->getNameAsString()); 4302d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string ByrefType; 4303d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefString(ByrefType, Name, ND, true); 4304d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " {\n"; 4305d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " void *__isa;\n"; 4306d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 4307d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " *__forwarding;\n"; 4308d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " int __flags;\n"; 4309d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " int __size;\n"; 4310d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Add void *__Block_byref_id_object_copy; 4311d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // void *__Block_byref_id_object_dispose; if needed. 4312d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType Ty = ND->getType(); 4313d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty); 4314d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasCopyAndDispose) { 4315d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; 4316d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; 4317d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4318d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4319d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType T = Ty; 4320d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian (void)convertBlockPointerToFunctionPointer(T); 4321d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian T.getAsStringInternal(Name, Context->getPrintingPolicy()); 4322d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4323d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " " + Name + ";\n"; 4324d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += "};\n"; 4325d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Insert this type in global scope. It is needed by helper function. 4326d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation FunLocStart; 4327d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CurFunctionDef) 4328d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FunLocStart = CurFunctionDef->getTypeSpecStartLoc(); 4329d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else { 4330d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); 4331d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FunLocStart = CurMethodDef->getLocStart(); 4332d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4333d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(FunLocStart, ByrefType); 4334d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Ty.isObjCGCWeak()) { 4335d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian flag |= BLOCK_FIELD_IS_WEAK; 4336d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian isa = 1; 4337d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 43388611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian 4339d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasCopyAndDispose) { 4340d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian flag = BLOCK_BYREF_CALLER; 4341d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType Ty = ND->getType(); 4342d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. 4343d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Ty->isBlockPointerType()) 4344d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian flag |= BLOCK_FIELD_IS_BLOCK; 4345d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 4346d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian flag |= BLOCK_FIELD_IS_OBJECT; 4347d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); 4348d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!HF.empty()) 4349d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(FunLocStart, HF); 4350d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4351d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4352d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // struct __Block_byref_ND ND = 4353d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 4354d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // initializer-if-any}; 4355d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool hasInit = (ND->getInit() != 0); 4356d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned flags = 0; 4357d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasCopyAndDispose) 4358d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian flags |= BLOCK_HAS_COPY_DISPOSE; 4359d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Name = ND->getNameAsString(); 4360d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType.clear(); 4361d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 4362d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string ForwardingCastType("("); 4363d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ForwardingCastType += ByrefType + " *)"; 4364d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!hasInit) { 4365d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " " + Name + " = {(void*)"; 4366d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += utostr(isa); 4367d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 4368d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += utostr(flags); 4369d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += ", "; 4370d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += "sizeof("; 4371d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 4372d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += ")"; 4373d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasCopyAndDispose) { 4374d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += ", __Block_byref_id_object_copy_"; 4375d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += utostr(flag); 4376d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += ", __Block_byref_id_object_dispose_"; 4377d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += utostr(flag); 4378d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4379d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += "};\n"; 4380d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned nameSize = Name.size(); 4381d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // for block or function pointer declaration. Name is aleady 4382d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // part of the declaration. 4383d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) 4384d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian nameSize = 1; 4385d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType); 4386d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4387d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else { 4388d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation startLoc; 4389d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *E = ND->getInit(); 4390d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 4391d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian startLoc = ECE->getLParenLoc(); 4392d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 4393d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian startLoc = E->getLocStart(); 4394d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian startLoc = SM->getExpansionLoc(startLoc); 4395d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian endBuf = SM->getCharacterData(startLoc); 4396d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " " + Name; 4397d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += " = {(void*)"; 4398d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += utostr(isa); 4399d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 4400d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += utostr(flags); 4401d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += ", "; 4402d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += "sizeof("; 4403d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 4404d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += "), "; 4405d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasCopyAndDispose) { 4406d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += "__Block_byref_id_object_copy_"; 4407d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += utostr(flag); 4408d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += ", __Block_byref_id_object_dispose_"; 4409d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += utostr(flag); 4410d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ByrefType += ", "; 4411d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4412d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); 4413d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4414d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Complete the newly synthesized compound expression by inserting a right 4415d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // curly brace before the end of the declaration. 4416d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME: This approach avoids rewriting the initializer expression. It 4417d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // also assumes there is only one declarator. For example, the following 4418d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // isn't currently supported by this routine (in general): 4419d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 4420d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37; 4421d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 4422d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *startInitializerBuf = SM->getCharacterData(startLoc); 4423d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *semiBuf = strchr(startInitializerBuf, ';'); 4424d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'"); 4425d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation semiLoc = 4426d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian startLoc.getLocWithOffset(semiBuf-startInitializerBuf); 4427d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4428d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(semiLoc, "}"); 4429d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4430d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 4431d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 4432d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4433d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { 4434d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Add initializers for any closure decl refs. 4435d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GetBlockDeclRefExprs(Exp->getBody()); 4436d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefs.size()) { 4437d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Unique all "by copy" declarations. 4438d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 4439d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!BlockDeclRefs[i]->isByRef()) { 4440d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 4441d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 4442d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); 4443d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4444d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4445d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Unique all "by ref" declarations. 4446d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 4447d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefs[i]->isByRef()) { 4448d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 4449d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 4450d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); 4451d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4452d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4453d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Find any imported blocks...they will need special attention. 4454d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 4455d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefs[i]->isByRef() || 4456d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 4457d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs[i]->getType()->isBlockPointerType()) 4458d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); 4459d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4460d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 4461d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4462d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz JahanianFunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) { 4463d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IdentifierInfo *ID = &Context->Idents.get(name); 4464d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); 4465d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), 4466d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), ID, FType, 0, SC_Extern, 4467d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SC_None, false, false); 4468d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 4469d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4470d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz JahanianStmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, 4471d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) { 4472d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const BlockDecl *block = Exp->getBlockDecl(); 4473d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Blocks.push_back(Exp); 4474d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4475d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CollectBlockDeclRefInfo(Exp); 4476d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4477d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Add inner imported variables now used in current block. 4478d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int countOfInnerDecls = 0; 4479d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!InnerBlockDeclRefs.empty()) { 4480d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { 4481d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i]; 448272952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian ValueDecl *VD = Exp->getDecl(); 448372952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) { 4484d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // We need to save the copied-in variables in nested 4485d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // blocks because it is needed at the end for some of the API generations. 4486d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // See SynthesizeBlockLiterals routine. 4487d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 4488d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs.push_back(Exp); 448972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByCopyDeclsPtrSet.insert(VD); 449072952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByCopyDecls.push_back(VD); 449172952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 449272952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) { 4493d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 4494d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs.push_back(Exp); 449572952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByRefDeclsPtrSet.insert(VD); 449672952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByRefDecls.push_back(VD); 449772952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 449872952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 4499d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Find any imported blocks...they will need special attention. 4500d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) 4501d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (InnerBlockDeclRefs[i]->isByRef() || 4502d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 4503d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) 4504d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); 4505d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4506d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerDeclRefsCount.push_back(countOfInnerDecls); 4507d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4508d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string FuncName; 450954055232a5ddb9529726e934301b125cb720a273Steve Naroff 4510d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CurFunctionDef) 4511d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FuncName = CurFunctionDef->getNameAsString(); 4512d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (CurMethodDef) 4513d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BuildUniqueMethodName(FuncName, CurMethodDef); 4514d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (GlobalVarDecl) 4515d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FuncName = std::string(GlobalVarDecl->getNameAsString()); 45161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4517d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string BlockNumber = utostr(Blocks.size()-1); 451854055232a5ddb9529726e934301b125cb720a273Steve Naroff 4519d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber; 4520d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; 452154055232a5ddb9529726e934301b125cb720a273Steve Naroff 4522d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Get a pointer to the function type so we can cast appropriately. 4523d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType()); 4524d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType FType = Context->getPointerType(BFT); 45251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4526d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FunctionDecl *FD; 4527d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *NewRep; 452854055232a5ddb9529726e934301b125cb720a273Steve Naroff 4529d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Simulate a contructor call... 4530d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD = SynthBlockInitFunctionDecl(Tag); 4531d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, VK_RValue, 4532d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 45331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4534d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<Expr*, 4> InitExprs; 4535d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4536d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Initialize the block function. 4537d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD = SynthBlockInitFunctionDecl(Func); 4538d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 4539d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 4540d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 4541d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CK_BitCast, Arg); 4542d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InitExprs.push_back(castExpr); 4543d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4544d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Initialize the block descriptor. 4545d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; 4546d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4547d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, 4548d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), SourceLocation(), 4549d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian &Context->Idents.get(DescData.c_str()), 4550d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->VoidPtrTy, 0, 4551d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SC_Static, SC_None); 4552d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian UnaryOperator *DescRefExpr = 4553d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, 4554d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->VoidPtrTy, 4555d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VK_LValue, 4556d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()), 4557d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian UO_AddrOf, 4558d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getPointerType(Context->VoidPtrTy), 4559d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VK_RValue, OK_Ordinary, 4560d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 4561d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InitExprs.push_back(DescRefExpr); 4562d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4563d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Add initializers for any closure decl refs. 4564d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefs.size()) { 4565d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *Exp; 4566d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output all "by copy" declarations. 4567d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 4568d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BlockByCopyDecls.end(); I != E; ++I) { 4569d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isObjCType((*I)->getType())) { 4570d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME: Conform to ABI ([[obj retain] autorelease]). 4571d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD = SynthBlockInitFunctionDecl((*I)->getName()); 4572d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 4573d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 4574d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasLocalVariableExternalStorage(*I)) { 4575d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType QT = (*I)->getType(); 4576d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT = Context->getPointerType(QT); 4577d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 4578d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OK_Ordinary, SourceLocation()); 4579d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4580d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else if (isTopLevelBlockPointerType((*I)->getType())) { 4581d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD = SynthBlockInitFunctionDecl((*I)->getName()); 4582d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 4583d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 4584d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 4585d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CK_BitCast, Arg); 4586d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 4587d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD = SynthBlockInitFunctionDecl((*I)->getName()); 4588d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 4589d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 4590d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasLocalVariableExternalStorage(*I)) { 4591d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType QT = (*I)->getType(); 4592d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QT = Context->getPointerType(QT); 4593d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 4594d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OK_Ordinary, SourceLocation()); 4595d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4596d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4597d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4598d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InitExprs.push_back(Exp); 4599d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4600d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output all "by ref" declarations. 4601d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 4602d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = BlockByRefDecls.end(); I != E; ++I) { 4603d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ValueDecl *ND = (*I); 4604d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Name(ND->getNameAsString()); 4605d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string RecName; 4606d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefString(RecName, Name, ND, true); 4607d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 4608d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian + sizeof("struct")); 4609d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 4610d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), SourceLocation(), 4611d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian II); 4612d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); 4613d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 4614d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4615d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD = SynthBlockInitFunctionDecl((*I)->getName()); 4616d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, 4617d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 4618d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool isNestedCapturedVar = false; 4619d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (block) 4620d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 4621d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ce = block->capture_end(); ci != ce; ++ci) { 4622d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const VarDecl *variable = ci->getVariable(); 4623d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (variable == ND && ci->isNested()) { 4624d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert (ci->isByRef() && 4625d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "SynthBlockInitExpr - captured block variable is not byref"); 4626d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian isNestedCapturedVar = true; 4627d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 4628d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4629d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4630d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // captured nested byref variable has its address passed. Do not take 4631d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // its address again. 4632d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!isNestedCapturedVar) 4633d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, 4634d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getPointerType(Exp->getType()), 4635d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VK_RValue, OK_Ordinary, SourceLocation()); 4636d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); 4637d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InitExprs.push_back(Exp); 4638d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 463954055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4640d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ImportedBlockDecls.size()) { 4641d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR 4642d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR); 4643d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned IntSize = 4644d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 4645d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 4646d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->IntTy, SourceLocation()); 4647d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InitExprs.push_back(FlagExp); 464861b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian } 4649d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(), 4650d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FType, VK_LValue, SourceLocation()); 4651d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, 4652d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getPointerType(NewRep->getType()), 4653d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VK_RValue, OK_Ordinary, SourceLocation()); 4654d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, 4655d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian NewRep); 4656d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockDeclRefs.clear(); 4657d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDecls.clear(); 4658d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDeclsPtrSet.clear(); 4659d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByCopyDecls.clear(); 4660d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByCopyDeclsPtrSet.clear(); 4661d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedBlockDecls.clear(); 4662d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return NewRep; 466354055232a5ddb9529726e934301b125cb720a273Steve Naroff} 466454055232a5ddb9529726e934301b125cb720a273Steve Naroff 4665d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianbool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { 4666d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (const ObjCForCollectionStmt * CS = 4667d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian dyn_cast<ObjCForCollectionStmt>(Stmts.back())) 4668d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return CS->getElement() == DS; 4669d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return false; 467054055232a5ddb9529726e934301b125cb720a273Steve Naroff} 467154055232a5ddb9529726e934301b125cb720a273Steve Naroff 4672d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian//===----------------------------------------------------------------------===// 4673d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// Function Body / Expression rewriting 4674d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian//===----------------------------------------------------------------------===// 4675e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian 4676d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz JahanianStmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { 4677d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 4678d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian isa<DoStmt>(S) || isa<ForStmt>(S)) 4679d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmts.push_back(S); 4680d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (isa<ObjCForCollectionStmt>(S)) { 4681d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmts.push_back(S); 4682d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCBcLabelNo.push_back(++BcLabelCount); 4683d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 468454055232a5ddb9529726e934301b125cb720a273Steve Naroff 4685d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Pseudo-object operations and ivar references need special 4686d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // treatment because we're going to recursively rewrite them. 4687d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) { 4688d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) { 4689d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewritePropertyOrImplicitSetter(PseudoOp); 4690d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 4691d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewritePropertyOrImplicitGetter(PseudoOp); 469254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4693d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 4694d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteObjCIvarRefExpr(IvarRefExpr); 46956cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 469654055232a5ddb9529726e934301b125cb720a273Steve Naroff 4697d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceRange OrigStmtRange = S->getSourceRange(); 4698d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4699d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Perform a bottom up rewrite of all children. 47007502c1d3ce8bb97bcc4f7bebef507040bd93b26fJohn McCall for (Stmt::child_range CI = S->children(); CI; ++CI) 47015e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian if (*CI) { 4702d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmt *childStmt = (*CI); 4703d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt); 4704d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (newStmt) { 4705d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian *CI = newStmt; 4706d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 47075e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian } 47085e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 4709d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { 4710d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs; 4711d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; 4712d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerContexts.insert(BE->getBlockDecl()); 4713d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedLocalExternalDecls.clear(); 4714d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GetInnerBlockDeclRefExprs(BE->getBody(), 4715d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InnerBlockDeclRefs, InnerContexts); 4716d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Rewrite the block body in place. 4717d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmt *SaveCurrentBody = CurrentBody; 4718d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurrentBody = BE->getBody(); 4719d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PropParentMap = 0; 4720d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // block literal on rhs of a property-dot-sytax assignment 4721d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // must be replaced by its synthesize ast so getRewrittenText 4722d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // works as expected. In this case, what actually ends up on RHS 4723d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // is the blockTranscribed which is the helper function for the 4724d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // block literal; as in: self.c = ^() {[ace ARR];}; 4725d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool saveDisableReplaceStmt = DisableReplaceStmt; 4726d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DisableReplaceStmt = false; 4727d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); 4728d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DisableReplaceStmt = saveDisableReplaceStmt; 4729d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurrentBody = SaveCurrentBody; 4730d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PropParentMap = 0; 4731d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ImportedLocalExternalDecls.clear(); 4732d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Now we snarf the rewritten text and stash it away for later use. 4733d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); 4734d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewrittenBlockExprs[BE] = Str; 4735d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4736d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); 4737d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4738d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian //blockTranscribed->dump(); 4739d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceStmt(S, blockTranscribed); 4740d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return blockTranscribed; 47411f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian } 4742d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Handle specific things. 4743d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) 4744d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteAtEncode(AtEncode); 47451f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian 4746d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) 4747d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteAtSelector(AtSelector); 47481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4749d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) 4750d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteObjCStringLiteral(AtString); 47511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4752d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { 4753d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian#if 0 4754d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Before we rewrite it, put the original message expression in a comment. 4755d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation startLoc = MessExpr->getLocStart(); 4756d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation endLoc = MessExpr->getLocEnd(); 475754055232a5ddb9529726e934301b125cb720a273Steve Naroff 4758d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 4759d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *endBuf = SM->getCharacterData(endLoc); 47601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4761d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string messString; 4762d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian messString += "// "; 4763d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian messString.append(startBuf, endBuf-startBuf+1); 4764d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian messString += "\n"; 4765d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4766d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME: Missing definition of 4767d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // InsertText(clang::SourceLocation, char const*, unsigned int). 4768d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // InsertText(startLoc, messString.c_str(), messString.size()); 4769d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Tried this, but it didn't work either... 4770d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); 4771d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian#endif 4772d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteMessageExpr(MessExpr); 4773aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff } 47741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4775d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) 4776d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteObjCTryStmt(StmtTry); 47771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4778d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) 4779d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteObjCSynchronizedStmt(StmtTry); 47801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4781d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) 4782d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteObjCThrowStmt(StmtThrow); 47831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4784d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) 4785d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteObjCProtocolExpr(ProtocolExp); 47861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4787d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCForCollectionStmt *StmtForCollection = 4788d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian dyn_cast<ObjCForCollectionStmt>(S)) 4789d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteObjCForCollectionStmt(StmtForCollection, 4790d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OrigStmtRange.getEnd()); 4791d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BreakStmt *StmtBreakStmt = 4792d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian dyn_cast<BreakStmt>(S)) 4793d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteBreakStmt(StmtBreakStmt); 4794d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ContinueStmt *StmtContinueStmt = 4795d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian dyn_cast<ContinueStmt>(S)) 4796d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteContinueStmt(StmtContinueStmt); 479754055232a5ddb9529726e934301b125cb720a273Steve Naroff 4798d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls 4799d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // and cast exprs. 4800d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 4801d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME: What we're doing here is modifying the type-specifier that 4802d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // precedes the first Decl. In the future the DeclGroup should have 4803d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // a separate type-specifier that we can rewrite. 4804d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // NOTE: We need to avoid rewriting the DeclStmt if it is within 4805d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // the context of an ObjCForCollectionStmt. For example: 4806d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // NSArray *someArray; 4807d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // for (id <FooProtocol> index in someArray) ; 4808d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // This is because RewriteObjCForCollectionStmt() does textual rewriting 4809d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // and it depends on the original text locations/positions. 4810d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS)) 4811d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); 48121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4813d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Blocks rewrite rules. 4814d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 4815d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DI != DE; ++DI) { 4816d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Decl *SD = *DI; 4817d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { 4818d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType(ND->getType())) 4819d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerDecl(ND); 4820d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (ND->getType()->isFunctionPointerType()) 4821d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CheckFunctionPointerDecl(ND->getType(), ND); 4822d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { 4823d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VD->hasAttr<BlocksAttr>()) { 4824d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static unsigned uniqueByrefDeclCount = 0; 4825d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(!BlockByRefDeclNo.count(ND) && 4826d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); 4827d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; 4828d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteByRefVar(VD); 4829d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4830d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 4831d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteTypeOfDecl(VD); 4832d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4833d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4834d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { 4835d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 4836d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerDecl(TD); 4837d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (TD->getUnderlyingType()->isFunctionPointerType()) 4838d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 4839d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 484054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 484154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 48421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4843d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) 4844d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCQualifiedInterfaceTypes(CE); 48451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4846d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 4847d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian isa<DoStmt>(S) || isa<ForStmt>(S)) { 4848d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(!Stmts.empty() && "Statement stack is empty"); 4849d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 4850d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 4851d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian && "Statement stack mismatch"); 4852d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmts.pop_back(); 4853d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4854d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Handle blocks rewriting. 4855d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) { 4856d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BDRE->isByRef()) 4857d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteBlockDeclRefExpr(BDRE); 4858d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4859d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 4860d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ValueDecl *VD = DRE->getDecl(); 4861d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VD->hasAttr<BlocksAttr>()) 4862d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteBlockDeclRefExpr(DRE); 4863d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (HasLocalVariableExternalStorage(VD)) 4864d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return RewriteLocalVariableExternalStorage(DRE); 4865d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4866d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4867d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 4868d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CE->getCallee()->getType()->isBlockPointerType()) { 4869d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); 4870d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceStmt(S, BlockCall); 4871d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return BlockCall; 487254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 487354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4874d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) { 4875d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteCastExpr(CE); 487654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4877d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian#if 0 4878d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 4879d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), 4880d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ICE->getSubExpr(), 4881d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation()); 4882d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Get the new text. 4883d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string SStr; 4884d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian llvm::raw_string_ostream Buf(SStr); 4885d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Replacement->printPretty(Buf, *Context); 4886d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const std::string &Str = Buf.str(); 4887d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 4888d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian printf("CAST = %s\n", &Str[0]); 4889d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size()); 4890d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian delete S; 4891d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return Replacement; 489254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4893d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian#endif 4894d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Return this stmt unmodified. 4895d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return S; 489654055232a5ddb9529726e934301b125cb720a273Steve Naroff} 489754055232a5ddb9529726e934301b125cb720a273Steve Naroff 4898d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::RewriteRecordBody(RecordDecl *RD) { 4899d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (RecordDecl::field_iterator i = RD->field_begin(), 4900d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian e = RD->field_end(); i != e; ++i) { 4901d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FieldDecl *FD = *i; 4902d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType(FD->getType())) 4903d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerDecl(FD); 4904d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (FD->getType()->isObjCQualifiedIdType() || 4905d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD->getType()->isObjCQualifiedInterfaceType()) 4906d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCQualifiedInterfaceTypes(FD); 4907e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian } 4908e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian} 4909e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian 4910d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// HandleDeclInMainFile - This is called for each top-level decl defined in the 4911d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// main file of the input. 4912d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::HandleDeclInMainFile(Decl *D) { 4913d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian switch (D->getKind()) { 4914d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::Function: { 4915d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FunctionDecl *FD = cast<FunctionDecl>(D); 4916d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (FD->isOverloadedOperator()) 4917d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 49181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4919d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Since function prototypes don't have ParmDecl's, we check the function 4920d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // prototype. This enables us to rewrite function declarations and 4921d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // definitions using the same code. 4922d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlocksInFunctionProtoType(FD->getType(), FD); 49231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4924d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME: If this should support Obj-C++, support CXXTryStmt 4925d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { 4926d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurFunctionDef = FD; 4927d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurFunctionDeclToDeclareForBlock = FD; 4928d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurrentBody = Body; 4929d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Body = 4930d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 4931d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FD->setBody(Body); 4932d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurrentBody = 0; 4933d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PropParentMap) { 4934d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian delete PropParentMap; 4935d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PropParentMap = 0; 4936d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4937d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // This synthesizes and inserts the block "impl" struct, invoke function, 4938d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // and any copy/dispose helper functions. 4939d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertBlockLiteralsWithinFunction(FD); 4940d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurFunctionDef = 0; 4941d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 4942d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4943d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 494454055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4945d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::ObjCMethod: { 4946d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); 4947d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CompoundStmt *Body = MD->getCompoundBody()) { 4948d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurMethodDef = MD; 4949d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurrentBody = Body; 4950d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Body = 4951d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 4952d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian MD->setBody(Body); 4953d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurrentBody = 0; 4954d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PropParentMap) { 4955d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian delete PropParentMap; 4956d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PropParentMap = 0; 4957d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4958d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertBlockLiteralsWithinMethod(MD); 4959d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurMethodDef = 0; 4960d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4961d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 4962d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4963d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::ObjCImplementation: { 4964d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D); 4965d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ClassImplementation.push_back(CI); 4966d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 4967d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4968d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::ObjCCategoryImpl: { 4969d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D); 4970d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CategoryImplementation.push_back(CI); 4971d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 4972d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4973d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::Var: { 4974d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VarDecl *VD = cast<VarDecl>(D); 4975d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCQualifiedInterfaceTypes(VD); 4976d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType(VD->getType())) 4977d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerDecl(VD); 4978d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (VD->getType()->isFunctionPointerType()) { 4979d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CheckFunctionPointerDecl(VD->getType(), VD); 4980d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VD->getInit()) { 4981d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 4982d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteCastExpr(CE); 4983d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4984d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4985d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else if (VD->getType()->isRecordType()) { 4986d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl(); 4987d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (RD->isCompleteDefinition()) 4988d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteRecordBody(RD); 4989d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4990d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (VD->getInit()) { 4991d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GlobalVarDecl = VD; 4992d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurrentBody = VD->getInit(); 4993d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); 4994d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CurrentBody = 0; 4995d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PropParentMap) { 4996d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian delete PropParentMap; 4997d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PropParentMap = 0; 4998d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 4999d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName()); 5000d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian GlobalVarDecl = 0; 5001d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5002d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // This is needed for blocks. 5003d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 5004d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteCastExpr(CE); 5005d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5006d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5007d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 5008d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5009d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::TypeAlias: 5010d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::Typedef: { 5011d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 5012d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 5013d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteBlockPointerDecl(TD); 5014d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else if (TD->getUnderlyingType()->isFunctionPointerType()) 5015d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 5016d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5017d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 5018d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5019d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::CXXRecord: 5020d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian case Decl::Record: { 5021d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RecordDecl *RD = cast<RecordDecl>(D); 5022d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (RD->isCompleteDefinition()) 5023d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteRecordBody(RD); 5024d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 5025d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5026d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian default: 5027d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 502854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 5029d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Nothing yet. 503054055232a5ddb9529726e934301b125cb720a273Steve Naroff} 503154055232a5ddb9529726e934301b125cb720a273Steve Naroff 5032d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjC::HandleTranslationUnit(ASTContext &C) { 5033d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Diags.hasErrorOccurred()) 503454055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 50351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5036d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteInclude(); 5037d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5038d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Here's a great place to add any extra declarations that may be needed. 5039d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Write out meta data for each @protocol(<expr>). 5040d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 5041d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = ProtocolExprDecls.end(); I != E; ++I) 5042d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCProtocolMetaData(*I, "", "", Preamble); 5043d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5044d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); 5045d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ClassImplementation.size() || CategoryImplementation.size()) 5046d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteImplementations(); 5047d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5048d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Get the buffer corresponding to MainFileID. If we haven't changed it, then 5049d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // we are done. 5050d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (const RewriteBuffer *RewriteBuf = 5051d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Rewrite.getRewriteBufferFor(MainFileID)) { 5052d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian //printf("Changed:\n"); 5053d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 5054d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 5055d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian llvm::errs() << "No changes\n"; 5056e985d01390a828d9ea679c26c711d5509fd27709Fariborz Jahanian } 5057d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5058d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ClassImplementation.size() || CategoryImplementation.size() || 5059d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ProtocolExprDecls.size()) { 5060d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Rewrite Objective-c meta data* 5061d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string ResultStr; 5062d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteMetaDataIntoBuffer(ResultStr); 5063d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Emit metadata. 5064d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian *OutFile << ResultStr; 506554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 5066d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OutFile->flush(); 506754055232a5ddb9529726e934301b125cb720a273Steve Naroff} 506854055232a5ddb9529726e934301b125cb720a273Steve Naroff 5069d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjCFragileABI::Initialize(ASTContext &context) { 5070d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InitializeCommon(context); 5071ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian 5072d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // declaring objc_selector outside the parameter list removes a silly 5073d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // scope related warning... 5074d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (IsHeader) 5075d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble = "#pragma once\n"; 5076d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "struct objc_selector; struct objc_class;\n"; 5077d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "struct __rw_objc_super { struct objc_object *object; "; 5078d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "struct objc_object *superClass; "; 5079d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (LangOpts.MicrosoftExt) { 5080d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Add a constructor for creating temporary objects. 5081d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) " 5082d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ": "; 5083d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "object(o), superClass(s) {} "; 5084d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5085d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "};\n"; 5086d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; 5087d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "typedef struct objc_object Protocol;\n"; 5088d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define _REWRITER_typedef_Protocol\n"; 5089d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#endif\n"; 5090d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (LangOpts.MicrosoftExt) { 5091d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; 5092d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; 5093d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else 5094d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; 5095d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend"; 5096d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5097d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper"; 5098d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 5099d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret"; 5100d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5101d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret"; 5102d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 5103d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret"; 5104d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5105d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass"; 5106d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(const char *);\n"; 5107d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; 5108d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(struct objc_class *);\n"; 5109d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass"; 5110d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(const char *);\n"; 5111d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n"; 5112d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n"; 5113d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n"; 5114d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n"; 5115d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match"; 5116d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "(struct objc_class *, struct objc_object *);\n"; 5117d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // @synchronized hooks. 5118d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n"; 5119d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n"; 5120d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; 5121d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; 5122d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "struct __objcFastEnumerationState {\n\t"; 5123d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "unsigned long state;\n\t"; 5124d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "void **itemsPtr;\n\t"; 5125d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "unsigned long *mutationsPtr;\n\t"; 5126d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "unsigned long extra[5];\n};\n"; 5127d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; 5128d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __FASTENUMERATIONSTATE\n"; 5129d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#endif\n"; 5130d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; 5131d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "struct __NSConstantStringImpl {\n"; 5132d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += " int *isa;\n"; 5133d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += " int flags;\n"; 5134d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += " char *str;\n"; 5135d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += " long length;\n"; 5136d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "};\n"; 5137d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; 5138d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; 5139d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#else\n"; 5140d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; 5141d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#endif\n"; 5142d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; 5143d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#endif\n"; 5144d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Blocks preamble. 5145d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#ifndef BLOCK_IMPL\n"; 5146d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define BLOCK_IMPL\n"; 5147d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "struct __block_impl {\n"; 5148d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += " void *isa;\n"; 5149d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += " int Flags;\n"; 5150d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += " int Reserved;\n"; 5151d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += " void *FuncPtr;\n"; 5152d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "};\n"; 5153d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; 5154d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; 5155d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "extern \"C\" __declspec(dllexport) " 5156d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "void _Block_object_assign(void *, const void *, const int);\n"; 5157d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; 5158d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; 5159d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; 5160d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#else\n"; 5161d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; 5162d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; 5163d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; 5164d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; 5165d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#endif\n"; 5166d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#endif\n"; 5167d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (LangOpts.MicrosoftExt) { 5168d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; 5169d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; 5170d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. 5171d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __attribute__(X)\n"; 5172d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#endif\n"; 5173d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __weak\n"; 5174f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian } 5175dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian else { 5176d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __block\n"; 5177d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "#define __weak\n"; 5178dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian } 5179d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long 5180d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // as this avoids warning in any 64bit/32bit compilation model. 5181d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; 5182d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 5183d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5184d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// RewriteIvarOffsetComputation - This rutine synthesizes computation of 5185d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// ivar offset. 5186d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 5187d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) { 5188d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ivar->isBitField()) { 5189d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME: The hack below doesn't work for bitfields. For now, we simply 5190d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // place all bitfields at offset 0. 5191d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "0"; 5192d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 5193d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "__OFFSETOFIVAR__(struct "; 5194d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ivar->getContainingInterface()->getNameAsString(); 5195d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (LangOpts.MicrosoftExt) 5196d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "_IMPL"; 5197d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", "; 5198d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ivar->getNameAsString(); 5199d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ")"; 52002086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian } 5201d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 5202d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5203d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. 5204d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjCFragileABI::RewriteObjCProtocolMetaData( 5205d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCProtocolDecl *PDecl, StringRef prefix, 5206d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef ClassName, std::string &Result) { 5207d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static bool objc_protocol_methods = false; 52082086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian 5209d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output struct protocol_methods holder of method selector and type. 52105e2a1ff9f28d2eab256d2553e76a9c9d54693875Douglas Gregor if (!objc_protocol_methods && PDecl->hasDefinition()) { 5211d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct protocol_methods { 5212d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SEL _cmd; 5213d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian char *method_types; 5214d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5215d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5216d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstruct _protocol_methods {\n"; 5217d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct objc_selector *_cmd;\n"; 5218d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tchar *method_types;\n"; 5219d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 5220d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5221d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian objc_protocol_methods = true; 5222d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 5223d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Do not synthesize the protocol more than once. 52243fc73ee0c613715ebce78e30b4d050ea715a007dDouglas Gregor if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl())) 5225d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return; 522652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian 522761cc296de6c1f82fa84c0abb3ecd142a584838efDouglas Gregor if (ObjCProtocolDecl *Def = PDecl->getDefinition()) 522861cc296de6c1f82fa84c0abb3ecd142a584838efDouglas Gregor PDecl = Def; 522961cc296de6c1f82fa84c0abb3ecd142a584838efDouglas Gregor 5230d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 5231d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned NumMethods = std::distance(PDecl->instmeth_begin(), 5232d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PDecl->instmeth_end()); 5233d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct _objc_protocol_method_list { 5234d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int protocol_method_count; 5235d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct protocol_methods protocols[]; 5236d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5237d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5238d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct {\n"; 5239d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tint protocol_method_count;\n"; 5240d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _protocol_methods protocol_methods["; 5241d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += utostr(NumMethods); 5242d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_"; 5243d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += PDecl->getNameAsString(); 5244d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 5245d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "{\n\t" + utostr(NumMethods) + "\n"; 5246d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5247d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output instance methods declared in this protocol. 5248d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (ObjCProtocolDecl::instmeth_iterator 5249d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 5250d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian I != E; ++I) { 5251d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (I == PDecl->instmeth_begin()) 5252d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t ,{{(struct objc_selector *)\""; 5253d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5254d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t ,{(struct objc_selector *)\""; 5255d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (*I)->getSelector().getAsString(); 5256d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string MethodTypeString; 5257d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); 5258d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", \""; 5259d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += MethodTypeString; 5260d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\"}\n"; 5261d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 5262d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t }\n};\n"; 526352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian } 5264d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5265d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output class methods declared in this protocol. 5266d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned NumMethods = std::distance(PDecl->classmeth_begin(), 5267d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PDecl->classmeth_end()); 5268d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (NumMethods > 0) { 5269d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct _objc_protocol_method_list { 5270d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int protocol_method_count; 5271d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct protocol_methods protocols[]; 5272d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5273d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5274d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct {\n"; 5275d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tint protocol_method_count;\n"; 5276d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _protocol_methods protocol_methods["; 5277d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += utostr(NumMethods); 5278d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_"; 5279d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += PDecl->getNameAsString(); 5280d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5281d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "{\n\t"; 5282d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += utostr(NumMethods); 5283d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5284d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5285d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output instance methods declared in this protocol. 5286d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (ObjCProtocolDecl::classmeth_iterator 5287d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 5288d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian I != E; ++I) { 5289d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (I == PDecl->classmeth_begin()) 5290d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t ,{{(struct objc_selector *)\""; 5291d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5292d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t ,{(struct objc_selector *)\""; 5293d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (*I)->getSelector().getAsString(); 5294d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string MethodTypeString; 5295d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); 5296d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", \""; 5297d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += MethodTypeString; 5298d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\"}\n"; 5299d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 5300d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t }\n};\n"; 5301d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5302d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5303d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output: 5304d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct _objc_protocol { 5305d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Objective-C 1.0 extensions 5306d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_protocol_extension *isa; 5307d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian char *protocol_name; 5308d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_protocol **protocol_list; 5309d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_protocol_method_list *instance_methods; 5310d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_protocol_method_list *class_methods; 5311d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian }; 5312d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5313d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static bool objc_protocol = false; 5314d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!objc_protocol) { 5315d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstruct _objc_protocol {\n"; 5316d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_protocol_extension *isa;\n"; 5317d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tchar *protocol_name;\n"; 5318d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_protocol **protocol_list;\n"; 5319d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_protocol_method_list *instance_methods;\n"; 5320d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_protocol_method_list *class_methods;\n"; 5321d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 5322c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff 5323d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian objc_protocol = true; 532452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian } 5325d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5326d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_"; 5327d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += PDecl->getNameAsString(); 5328d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 5329d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "{\n\t0, \""; 5330d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += PDecl->getNameAsString(); 5331d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", 0, "; 5332d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 5333d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; 5334d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += PDecl->getNameAsString(); 5335d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", "; 533654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 5337d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5338d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "0, "; 5339d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PDecl->classmeth_begin() != PDecl->classmeth_end()) { 5340d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; 5341d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += PDecl->getNameAsString(); 5342d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5343d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5344d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5345d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "0\n"; 5346d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 5347d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5348d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Mark this protocol as having been generated. 53493fc73ee0c613715ebce78e30b4d050ea715a007dDouglas Gregor if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl())) 5350d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian llvm_unreachable("protocol already synthesized"); 5351d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 535254055232a5ddb9529726e934301b125cb720a273Steve Naroff} 535354055232a5ddb9529726e934301b125cb720a273Steve Naroff 5354d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjCFragileABI::RewriteObjCProtocolListMetaData( 5355d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const ObjCList<ObjCProtocolDecl> &Protocols, 5356d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef prefix, StringRef ClassName, 5357d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) { 5358d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (Protocols.empty()) return; 5359d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5360d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (unsigned i = 0; i != Protocols.size(); i++) 5361d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result); 5362d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5363d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Output the top lovel protocol meta-data for the class. 5364d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct _objc_protocol_list { 5365d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_protocol_list *next; 5366d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int protocol_count; 5367d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_protocol *class_protocols[]; 5368d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5369d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5370d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct {\n"; 5371d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_protocol_list *next;\n"; 5372d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tint protocol_count;\n"; 5373d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_protocol *class_protocols["; 5374d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += utostr(Protocols.size()); 5375d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "];\n} _OBJC_"; 5376d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += prefix; 5377d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "_PROTOCOLS_"; 5378d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ClassName; 5379d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 5380d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "{\n\t0, "; 5381d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += utostr(Protocols.size()); 5382d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5383d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5384d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t,{&_OBJC_PROTOCOL_"; 5385d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += Protocols[0]->getNameAsString(); 5386d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " \n"; 5387d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5388d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (unsigned i = 1; i != Protocols.size(); i++) { 5389d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t ,&_OBJC_PROTOCOL_"; 5390d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += Protocols[i]->getNameAsString(); 5391d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5392d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5393d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t }\n};\n"; 5394fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5395fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5396d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 5397d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) { 5398d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 53995e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 5400d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Explicitly declared @interface's are already synthesized. 5401d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CDecl->isImplicitInterfaceDecl()) { 54027723fec9b45b7258c0eddf4cbfd0d335348f5edcDouglas Gregor // FIXME: Implementation of a class with no @interface (legacy) does not 5403d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // produce correct synthesis as yet. 5404d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCInternalStruct(CDecl, Result); 54055e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian } 540601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 5407d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Build _objc_ivar_list metadata for classes ivars if needed 5408d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned NumIvars = !IDecl->ivar_empty() 5409d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ? IDecl->ivar_size() 5410d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian : (CDecl ? CDecl->ivar_size() : 0); 5411d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (NumIvars > 0) { 5412d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static bool objc_ivar = false; 5413d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!objc_ivar) { 5414d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct _objc_ivar { 5415d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian char *ivar_name; 5416d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian char *ivar_type; 5417d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int ivar_offset; 5418d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian }; 5419d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5420d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstruct _objc_ivar {\n"; 5421d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tchar *ivar_name;\n"; 5422d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tchar *ivar_type;\n"; 5423d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tint ivar_offset;\n"; 5424d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 54252663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian 5426d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian objc_ivar = true; 5427d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5428d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5429d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct { 5430d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int ivar_count; 5431d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_ivar ivar_list[nIvars]; 5432d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian }; 5433d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5434d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct {\n"; 5435d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tint ivar_count;\n"; 5436d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_ivar ivar_list["; 5437d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += utostr(NumIvars); 5438d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "];\n} _OBJC_INSTANCE_VARIABLES_"; 5439d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += IDecl->getNameAsString(); 5440d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 5441d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "{\n\t"; 5442d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += utostr(NumIvars); 5443d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5444d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5445d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCInterfaceDecl::ivar_iterator IVI, IVE; 5446d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<ObjCIvarDecl *, 8> IVars; 5447d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!IDecl->ivar_empty()) { 5448d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (ObjCInterfaceDecl::ivar_iterator 5449d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); 5450d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV != IVEnd; ++IV) 5451d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IVars.push_back(*IV); 5452d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IVI = IDecl->ivar_begin(); 5453d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IVE = IDecl->ivar_end(); 5454d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 5455d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IVI = CDecl->ivar_begin(); 5456d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IVE = CDecl->ivar_end(); 5457fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5458d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t,{{\""; 5459d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (*IVI)->getNameAsString(); 5460d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", \""; 5461d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string TmpString, StrEncoding; 5462d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); 5463d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QuoteDoublequotes(TmpString, StrEncoding); 5464d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += StrEncoding; 5465d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", "; 5466d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteIvarOffsetComputation(*IVI, Result); 5467d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "}\n"; 5468d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (++IVI; IVI != IVE; ++IVI) { 5469d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t ,{\""; 5470d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (*IVI)->getNameAsString(); 5471d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", \""; 5472d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string TmpString, StrEncoding; 5473d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); 5474d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QuoteDoublequotes(TmpString, StrEncoding); 5475d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += StrEncoding; 5476d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", "; 5477d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteIvarOffsetComputation((*IVI), Result); 5478d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "}\n"; 5479d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5480d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5481d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t }\n};\n"; 548201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff } 5483d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5484d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Build _objc_method_list for class's instance methods if needed 5485d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<ObjCMethodDecl *, 32> 5486d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 5487d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5488d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // If any of our property implementations have associated getters or 5489d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // setters, produce metadata for them as well. 5490d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 5491d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PropEnd = IDecl->propimpl_end(); 5492d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Prop != PropEnd; ++Prop) { 5493d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 5494d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian continue; 5495d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!(*Prop)->getPropertyIvarDecl()) 5496d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian continue; 5497d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); 5498d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!PD) 5499d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian continue; 5500d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 5501d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!Getter->isDefined()) 5502d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InstanceMethods.push_back(Getter); 5503d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PD->isReadOnly()) 5504d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian continue; 5505d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 5506d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!Setter->isDefined()) 5507d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InstanceMethods.push_back(Setter); 5508d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5509d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 5510d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian true, "", IDecl->getName(), Result); 5511d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5512d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Build _objc_method_list for class's class methods if needed 5513d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 5514d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian false, "", IDecl->getName(), Result); 5515d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5516d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Protocols referenced in class declaration? 5517d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), 5518d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "CLASS", CDecl->getName(), Result); 5519d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5520d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Declaration of class/meta-class metadata 5521d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct _objc_class { 5522d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_class *isa; // or const char *root_class_name when metadata 5523d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *super_class_name; 5524d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian char *name; 5525d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian long version; 5526d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian long info; 5527d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian long instance_size; 5528d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_ivar_list *ivars; 5529d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_method_list *methods; 5530d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct objc_cache *cache; 5531d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct objc_protocol_list *protocols; 5532d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *ivar_layout; 5533d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_class_ext *ext; 5534d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian }; 5535d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5536d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static bool objc_class = false; 5537d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!objc_class) { 5538d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstruct _objc_class {\n"; 5539d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_class *isa;\n"; 5540d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tconst char *super_class_name;\n"; 5541d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tchar *name;\n"; 5542d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tlong version;\n"; 5543d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tlong info;\n"; 5544d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tlong instance_size;\n"; 5545d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_ivar_list *ivars;\n"; 5546d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_method_list *methods;\n"; 5547d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct objc_cache *cache;\n"; 5548d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_protocol_list *protocols;\n"; 5549d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tconst char *ivar_layout;\n"; 5550d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_class_ext *ext;\n"; 5551d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 5552d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian objc_class = true; 5553d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5554d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5555d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Meta-class metadata generation. 5556d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCInterfaceDecl *RootClass = 0; 5557d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); 5558d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian while (SuperClass) { 5559d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RootClass = SuperClass; 5560d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SuperClass = SuperClass->getSuperClass(); 5561d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5562d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SuperClass = CDecl->getSuperClass(); 5563d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5564d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; 5565d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5566d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 5567d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "{\n\t(struct _objc_class *)\""; 5568d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString()); 5569d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\""; 5570d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5571d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (SuperClass) { 5572d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", \""; 5573d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += SuperClass->getNameAsString(); 5574d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", \""; 5575d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5576d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\""; 5577d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5578d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else { 5579d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", 0, \""; 5580d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5581d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\""; 5582d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5583d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. 5584d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 'info' field is initialized to CLS_META(2) for metaclass 5585d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", 0,2, sizeof(struct _objc_class), 0"; 5586d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 5587d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; 5588d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += IDecl->getNameAsString(); 5589d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5590d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5591d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5592d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", 0\n"; 5593d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CDecl->protocol_begin() != CDecl->protocol_end()) { 5594d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; 5595d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5596d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ",0,0\n"; 5597d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5598d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5599d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t,0,0,0,0\n"; 5600d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 5601d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5602d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // class metadata generation. 5603d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct _objc_class _OBJC_CLASS_"; 5604d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5605d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= " 5606d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "{\n\t&_OBJC_METACLASS_"; 5607d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5608d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (SuperClass) { 5609d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", \""; 5610d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += SuperClass->getNameAsString(); 5611d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", \""; 5612d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5613d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\""; 5614d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5615d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else { 5616d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", 0, \""; 5617d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5618d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\""; 5619fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5620d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // 'info' field is initialized to CLS_CLASS(1) for class 5621d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", 0,1"; 5622d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!ObjCSynthesizedStructs.count(CDecl)) 5623d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ",0"; 5624d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else { 5625d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // class has size. Must synthesize its size. 5626d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ",sizeof(struct "; 5627d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5628d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (LangOpts.MicrosoftExt) 5629d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "_IMPL"; 5630d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ")"; 5631fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5632d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (NumIvars > 0) { 5633d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_"; 5634d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5635d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n\t"; 56364b9c2d235fb9449e249d74f48ecfec601650de93John McCall } 5637d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5638d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ",0"; 5639d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 5640d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; 5641d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5642d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", 0\n\t"; 5643fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5644d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5645d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ",0,0"; 5646d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CDecl->protocol_begin() != CDecl->protocol_end()) { 5647d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; 5648d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CDecl->getNameAsString(); 5649d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ", 0,0\n"; 5650fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5651d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5652d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ",0,0,0\n"; 5653d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 5654d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 56551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5656d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) { 5657d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int ClsDefCount = ClassImplementation.size(); 5658d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int CatDefCount = CategoryImplementation.size(); 5659d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5660d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // For each implemented class, write out all its meta data. 5661d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (int i = 0; i < ClsDefCount; i++) 5662d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCClassMetaData(ClassImplementation[i], Result); 5663d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5664d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // For each implemented category, write out all its meta data. 5665d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (int i = 0; i < CatDefCount; i++) 5666d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); 5667d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5668d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Write objc_symtab metadata 5669d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* 5670d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_symtab 5671d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian { 5672d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian long sel_ref_cnt; 5673d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SEL *refs; 5674d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian short cls_def_cnt; 5675d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian short cat_def_cnt; 5676d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian void *defs[cls_def_cnt + cat_def_cnt]; 5677d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian }; 5678d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5679d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5680d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstruct _objc_symtab {\n"; 5681d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tlong sel_ref_cnt;\n"; 5682d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tSEL *refs;\n"; 5683d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tshort cls_def_cnt;\n"; 5684d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tshort cat_def_cnt;\n"; 5685d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n"; 5686d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n\n"; 5687d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5688d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "static struct _objc_symtab " 5689d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n"; 5690d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t0, 0, " + utostr(ClsDefCount) 5691d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian + ", " + utostr(CatDefCount) + "\n"; 5692d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (int i = 0; i < ClsDefCount; i++) { 5693d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t,&_OBJC_CLASS_"; 5694d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ClassImplementation[i]->getNameAsString(); 5695d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5696d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5697d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5698d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (int i = 0; i < CatDefCount; i++) { 5699d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t,&_OBJC_CATEGORY_"; 5700d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CategoryImplementation[i]->getClassInterface()->getNameAsString(); 5701d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "_"; 5702d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += CategoryImplementation[i]->getNameAsString(); 5703d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5704d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5705d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5706d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n\n"; 5707d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5708d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Write objc_module metadata 5709d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5710d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* 5711d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_module { 5712d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian long version; 5713d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian long size; 5714d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const char *name; 5715d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_symtab *symtab; 5716d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5717d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5718d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5719d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstruct _objc_module {\n"; 5720d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tlong version;\n"; 5721d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tlong size;\n"; 5722d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tconst char *name;\n"; 5723d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_symtab *symtab;\n"; 5724d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n\n"; 5725d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "static struct _objc_module " 5726d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n"; 5727d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t" + utostr(OBJC_ABI_VERSION) + 5728d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n"; 5729d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n\n"; 5730d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5731d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (LangOpts.MicrosoftExt) { 5732d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ProtocolExprDecls.size()) { 5733d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n"; 5734d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "#pragma data_seg(push, \".objc_protocol$B\")\n"; 5735d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 5736d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian E = ProtocolExprDecls.end(); I != E; ++I) { 5737d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_"; 5738d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (*I)->getNameAsString(); 5739d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " = &_OBJC_PROTOCOL_"; 5740d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (*I)->getNameAsString(); 5741d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ";\n"; 5742fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5743d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "#pragma data_seg(pop)\n\n"; 5744fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5745d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n"; 5746d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "#pragma data_seg(push, \".objc_module_info$B\")\n"; 5747d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "static struct _objc_module *_POINTER_OBJC_MODULES = "; 5748d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "&_OBJC_MODULES;\n"; 5749d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "#pragma data_seg(pop)\n\n"; 5750fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5751d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 57521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5753d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category 5754d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// implementation. 5755d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, 5756d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) { 5757d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 5758d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Find category declaration for this implementation. 5759d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCCategoryDecl *CDecl; 5760d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (CDecl = ClassDecl->getCategoryList(); CDecl; 5761d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CDecl = CDecl->getNextClassCategory()) 5762d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CDecl->getIdentifier() == IDecl->getIdentifier()) 5763d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian break; 5764d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5765d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string FullCategoryName = ClassDecl->getNameAsString(); 5766d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FullCategoryName += '_'; 5767d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FullCategoryName += IDecl->getNameAsString(); 5768d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5769d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Build _objc_method_list for class's instance methods if needed 5770d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SmallVector<ObjCMethodDecl *, 32> 5771d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 5772d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5773d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // If any of our property implementations have associated getters or 5774d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // setters, produce metadata for them as well. 5775d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 5776d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian PropEnd = IDecl->propimpl_end(); 5777d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Prop != PropEnd; ++Prop) { 5778d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 5779d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian continue; 5780d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!(*Prop)->getPropertyIvarDecl()) 5781d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian continue; 5782d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); 5783d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!PD) 5784d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian continue; 5785d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 5786d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InstanceMethods.push_back(Getter); 5787d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (PD->isReadOnly()) 5788d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian continue; 5789d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 5790d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian InstanceMethods.push_back(Setter); 5791fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5792d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 5793d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian true, "CATEGORY_", FullCategoryName.c_str(), 5794d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result); 5795d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5796d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Build _objc_method_list for class's class methods if needed 5797d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 5798d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian false, "CATEGORY_", FullCategoryName.c_str(), 5799d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result); 5800d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5801d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Protocols referenced in class declaration? 5802d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Null CDecl is case of a category implementation with no category interface 5803d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CDecl) 5804d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", 5805d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian FullCategoryName, Result); 5806d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct _objc_category { 5807d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian char *category_name; 5808d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian char *class_name; 5809d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_method_list *instance_methods; 5810d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_method_list *class_methods; 5811d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_protocol_list *protocols; 5812d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Objective-C 1.0 extensions 5813d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian uint32_t size; // sizeof (struct _objc_category) 5814d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_property_list *instance_properties; // category's own 5815d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // @property decl. 5816d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian }; 5817d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5818d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5819d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian static bool objc_category = false; 5820d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!objc_category) { 5821d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstruct _objc_category {\n"; 5822d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tchar *category_name;\n"; 5823d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tchar *class_name;\n"; 5824d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_method_list *instance_methods;\n"; 5825d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_method_list *class_methods;\n"; 5826d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_protocol_list *protocols;\n"; 5827d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tunsigned int size;\n"; 5828d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_property_list *instance_properties;\n"; 5829d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 5830d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian objc_category = true; 5831f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian } 5832d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct _objc_category _OBJC_CATEGORY_"; 5833d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += FullCategoryName; 5834d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\""; 5835d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += IDecl->getNameAsString(); 5836d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\"\n\t, \""; 5837d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ClassDecl->getNameAsString(); 5838d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\"\n"; 5839f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian 5840d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 5841d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t, (struct _objc_method_list *)" 5842d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "&_OBJC_CATEGORY_INSTANCE_METHODS_"; 5843d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += FullCategoryName; 5844d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5845fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5846d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5847d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t, 0\n"; 5848d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 5849d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t, (struct _objc_method_list *)" 5850d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian "&_OBJC_CATEGORY_CLASS_METHODS_"; 5851d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += FullCategoryName; 5852d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5853fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5854d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5855d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t, 0\n"; 5856d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5857d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) { 5858d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; 5859d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += FullCategoryName; 5860d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\n"; 5861d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5862d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian else 5863d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t, 0\n"; 5864d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t, sizeof(struct _objc_category), 0\n};\n"; 5865d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian} 5866fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5867d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or 5868d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian/// class methods. 5869d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahaniantemplate<typename MethodIterator> 5870d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanianvoid RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 5871d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian MethodIterator MethodEnd, 5872d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian bool IsInstanceMethod, 5873d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef prefix, 5874d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian StringRef ClassName, 5875d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string &Result) { 5876d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (MethodBegin == MethodEnd) return; 5877d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5878d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (!objc_impl_method) { 5879d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct _objc_method { 5880d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SEL _cmd; 5881d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian char *method_types; 5882d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian void *_imp; 5883d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5884d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5885d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstruct _objc_method {\n"; 5886d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tSEL _cmd;\n"; 5887d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tchar *method_types;\n"; 5888d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tvoid *_imp;\n"; 5889d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "};\n"; 5890d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5891d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian objc_impl_method = true; 5892d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5893d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5894d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Build _objc_method_list for class's methods if needed 5895d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5896d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian /* struct { 5897d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_method_list *next_method; 5898d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian int method_count; 5899d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian struct _objc_method method_list[]; 5900d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } 5901d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian */ 5902d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian unsigned NumMethods = std::distance(MethodBegin, MethodEnd); 5903d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\nstatic struct {\n"; 5904d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_method_list *next_method;\n"; 5905d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tint method_count;\n"; 5906d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\tstruct _objc_method method_list["; 5907d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += utostr(NumMethods); 5908d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "];\n} _OBJC_"; 5909d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += prefix; 5910d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; 5911d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "_METHODS_"; 5912d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += ClassName; 5913d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += " __attribute__ ((used, section (\"__OBJC, __"; 5914d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += IsInstanceMethod ? "inst" : "cls"; 5915d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "_meth\")))= "; 5916d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "{\n\t0, " + utostr(NumMethods) + "\n"; 5917d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5918d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t,{{(SEL)\""; 5919d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (*MethodBegin)->getSelector().getAsString().c_str(); 5920d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string MethodTypeString; 5921d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 5922d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", \""; 5923d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += MethodTypeString; 5924d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", (void *)"; 5925d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += MethodInternalNames[*MethodBegin]; 5926d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "}\n"; 5927d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { 5928d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t ,{(SEL)\""; 5929d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += (*MethodBegin)->getSelector().getAsString().c_str(); 5930d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string MethodTypeString; 5931d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 5932d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", \""; 5933d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += MethodTypeString; 5934d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\", (void *)"; 5935d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += MethodInternalNames[*MethodBegin]; 5936d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "}\n"; 5937fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5938d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Result += "\t }\n};\n"; 5939fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5940fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5941d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz JahanianStmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { 5942d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceRange OldRange = IV->getSourceRange(); 5943d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *BaseExpr = IV->getBase(); 5944d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5945d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Rewrite the base, but without actually doing replaces. 5946d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian { 5947d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian DisableReplaceStmtScope S(*this); 5948d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr)); 5949d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV->setBase(BaseExpr); 59503d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff } 5951d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5952d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCIvarDecl *D = IV->getDecl(); 5953d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5954d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Expr *Replacement = IV; 5955d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (CurMethodDef) { 5956d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BaseExpr->getType()->isObjCObjectPointerType()) { 5957d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const ObjCInterfaceType *iFaceDecl = 5958d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 5959d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); 5960d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // lookup which class implements the instance variable. 5961d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCInterfaceDecl *clsDeclared = 0; 5962d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 5963d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian clsDeclared); 5964d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 5965d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5966d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Synthesize an explicit cast to gain access to the ivar. 5967d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string RecName = clsDeclared->getIdentifier()->getName(); 5968d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RecName += "_IMPL"; 5969d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IdentifierInfo *II = &Context->Idents.get(RecName); 5970d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 5971d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), SourceLocation(), 5972d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian II); 5973d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 5974d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 5975d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 5976d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CK_BitCast, 5977d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV->getBase()); 5978d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Don't forget the parens to enforce the proper binding. 5979d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(), 5980d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian OldRange.getEnd(), 5981d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian castExpr); 5982d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (IV->isFreeIvar() && 598360ef308e51c71b760d7f598c1b763ceb7b768148Douglas Gregor declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) { 5984d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian MemberExpr *ME = new (Context) MemberExpr(PE, true, D, 5985d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV->getLocation(), 5986d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian D->getType(), 5987d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian VK_LValue, OK_Ordinary); 5988d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian Replacement = ME; 5989d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { 5990d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV->setBase(PE); 59918e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff } 599202f8396a440b7b7a0354159e5371d29934aedd9cFariborz Jahanian } 5993d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian } else { // we are outside a method. 5994d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); 5995d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 5996d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Explicit ivar refs need to have a cast inserted. 5997d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // FIXME: consider sharing some of this code with the code above. 5998d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian if (BaseExpr->getType()->isObjCObjectPointerType()) { 5999d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian const ObjCInterfaceType *iFaceDecl = 6000d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 6001d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // lookup which class implements the instance variable. 6002d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ObjCInterfaceDecl *clsDeclared = 0; 6003d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 6004d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian clsDeclared); 6005d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 6006d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 6007d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Synthesize an explicit cast to gain access to the ivar. 6008d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian std::string RecName = clsDeclared->getIdentifier()->getName(); 6009d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RecName += "_IMPL"; 6010d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IdentifierInfo *II = &Context->Idents.get(RecName); 6011d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 6012d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian SourceLocation(), SourceLocation(), 6013d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian II); 6014d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 6015d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 6016d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 6017d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian CK_BitCast, 6018d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV->getBase()); 6019d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Don't forget the parens to enforce the proper binding. 6020d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), 6021d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV->getBase()->getLocEnd(), castExpr); 6022d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Cannot delete IV->getBase(), since PE points to it. 6023d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // Replace the old base with the cast. This is important when doing 6024d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian // embedded rewrites. For example, [newInv->_container addObject:0]. 6025d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian IV->setBase(PE); 602602f8396a440b7b7a0354159e5371d29934aedd9cFariborz Jahanian } 6027fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 6028d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian 6029d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian ReplaceStmtWithRange(IV, Replacement, OldRange); 6030d5c3fa29c6a06ed9c74e03b4a96f786cbc156b7cFariborz Jahanian return Replacement; 6031fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 6032fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 6033