RewriteObjC.cpp revision 906082edf2aea1c6de2926f93a8d7121e49d2a54
1b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroff//===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===// 277cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 377cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// The LLVM Compiler Infrastructure 477cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 777cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 877cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner//===----------------------------------------------------------------------===// 977cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 1077cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// Hacks and fun related to the code rewriter. 1177cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner// 1277cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner//===----------------------------------------------------------------------===// 1377cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 149b414d3e2d0cb84512b55a3275a98490b090162aDaniel Dunbar#include "clang/Rewrite/ASTConsumers.h" 158a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner#include "clang/Rewrite/Rewriter.h" 1677cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner#include "clang/AST/AST.h" 1777cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner#include "clang/AST/ASTConsumer.h" 188599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff#include "clang/AST/ParentMap.h" 198a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner#include "clang/Basic/SourceManager.h" 20ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff#include "clang/Basic/IdentifierTable.h" 210750618b0beacdc9b0a9e210a661e4746823ced7Chris Lattner#include "clang/Basic/Diagnostic.h" 2226de4655a38b899e0f0dcef4175032175854d1cfChris Lattner#include "clang/Lex/Lexer.h" 236cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/MemoryBuffer.h" 246cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer#include "llvm/Support/raw_ostream.h" 25158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner#include "llvm/ADT/StringExtras.h" 2626e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian#include "llvm/ADT/SmallPtrSet.h" 27a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek#include "llvm/ADT/OwningPtr.h" 28ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian#include "llvm/ADT/DenseSet.h" 2972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian 3077cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattnerusing namespace clang; 31158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattnerusing llvm::utostr; 3277cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 3377cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattnernamespace { 34b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroff class RewriteObjC : public ASTConsumer { 3573e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian enum { 3673e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 3773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian block, ... */ 3873e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 3973e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the 4073e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian __block variable */ 4173e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 4273e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian helpers */ 4373e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 4473e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian support routines */ 4573e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_BYREF_CURRENT_MAX = 256 4673e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian }; 4773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian 4873e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian enum { 4973e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_NEEDS_FREE = (1 << 24), 5073e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_COPY_DISPOSE = (1 << 25), 5173e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_CXX_OBJ = (1 << 26), 5273e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_IS_GC = (1 << 27), 5373e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_IS_GLOBAL = (1 << 28), 5473e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian BLOCK_HAS_DESCRIPTOR = (1 << 29) 5573e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian }; 5673e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian 572c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner Rewriter Rewrite; 58e365c50a21cb02e0219433db0c4461566ad4a597Chris Lattner Diagnostic &Diags; 594f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff const LangOptions &LangOpts; 60f69cc5d6606fc65a76e3acd6eb6e13efd0098295Steve Naroff unsigned RewriteFailedDiag; 618c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff unsigned TryFinallyContainsReturnDiag; 621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6301c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner ASTContext *Context; 6477cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner SourceManager *SM; 65ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis TranslationUnitDecl *TUDecl; 662b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner FileID MainFileID; 6726de4655a38b899e0f0dcef4175032175854d1cfChris Lattner const char *MainFileStart, *MainFileEnd; 682c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner SourceLocation LastIncLoc; 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 70a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek llvm::SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; 71a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek llvm::SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; 72a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; 73fbfe82527dadb09c95609a742744d75a2322850cSteve Naroff llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; 74a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls; 75a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; 76e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian llvm::SmallVector<Stmt *, 32> Stmts; 77e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian llvm::SmallVector<int, 8> ObjCBcLabelNo; 78621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Remember all the @protocol(<expr>) expressions. 79621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; 80ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian 81ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian llvm::DenseSet<uint64_t> CopyDestroyCache; 82ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian 83d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff unsigned NumObjCStringLiterals; 841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 85ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff FunctionDecl *MsgSendFunctionDecl; 86874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff FunctionDecl *MsgSendSuperFunctionDecl; 8780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendStretFunctionDecl; 8880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendSuperStretFunctionDecl; 89acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian FunctionDecl *MsgSendFpretFunctionDecl; 90ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff FunctionDecl *GetClassFunctionDecl; 919bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff FunctionDecl *GetMetaClassFunctionDecl; 92d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian FunctionDecl *GetSuperClassFunctionDecl; 93934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff FunctionDecl *SelGetUidFunctionDecl; 949698464266660346fa2da1bddc3e6404a9819b25Steve Naroff FunctionDecl *CFStringFunctionDecl; 95c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff FunctionDecl *SuperContructorFunctionDecl; 961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff // ObjC string constant support. 98248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff VarDecl *ConstantStringClassReference; 99beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff RecordDecl *NSStringRecord; 1001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 101b586cce95c69161c771f7a966383beb4fc5dd394Fariborz Jahanian // ObjC foreach break/continue generation support. 102e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian int BcLabelCount; 1031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 104874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // Needed for super. 10554055232a5ddb9529726e934301b125cb720a273Steve Naroff ObjCMethodDecl *CurMethodDef; 106874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff RecordDecl *SuperStructDecl; 107d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff RecordDecl *ConstantStringDecl; 1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff TypeDecl *ProtocolTypeDecl; 110621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QualType getProtocolType(); 1111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // Needed for header files being rewritten 113b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian bool IsHeader; 1141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 115a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff std::string InFileName; 11666d6f048471aad6daf67b3ea804b54fbea72a076Eli Friedman llvm::raw_ostream* OutFile; 117c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman 118c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool SilenceRewriteMacroWarning; 119f292fcf6bd5118499a830e0950429effeb373c28Fariborz Jahanian bool objc_impl_method; 120c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman 121ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff std::string Preamble; 12254055232a5ddb9529726e934301b125cb720a273Steve Naroff 12354055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block expressions. 12454055232a5ddb9529726e934301b125cb720a273Steve Naroff llvm::SmallVector<BlockExpr *, 32> Blocks; 1255e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian llvm::SmallVector<int, 32> InnerDeclRefsCount; 1265e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian llvm::SmallVector<BlockDeclRefExpr *, 32> InnerDeclRefs; 1275e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 12854055232a5ddb9529726e934301b125cb720a273Steve Naroff llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs; 1291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13054055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block related declarations. 131bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian llvm::SmallVector<ValueDecl *, 8> BlockByCopyDecls; 132bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; 133bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian llvm::SmallVector<ValueDecl *, 8> BlockByRefDecls; 134bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; 135a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; 13654055232a5ddb9529726e934301b125cb720a273Steve Naroff llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; 1376cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls; 1386cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 13954055232a5ddb9529726e934301b125cb720a273Steve Naroff llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; 14054055232a5ddb9529726e934301b125cb720a273Steve Naroff 141c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // This maps a property to it's assignment statement. 142c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff llvm::DenseMap<ObjCPropertyRefExpr *, BinaryOperator *> PropSetters; 1438599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // This maps a property to it's synthesied message expression. 1448599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // This allows us to rewrite chained getters (e.g. o.a.b.c). 1458599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff llvm::DenseMap<ObjCPropertyRefExpr *, Stmt *> PropGetters; 1461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1474c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // This maps an original source AST to it's rewritten form. This allows 1484c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // us to avoid rewriting the same node twice (which is very uncommon). 1494c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // This is needed to support some of the exotic property rewriting. 1504c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; 15115f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 15254055232a5ddb9529726e934301b125cb720a273Steve Naroff FunctionDecl *CurFunctionDef; 153abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FunctionDecl *CurFunctionDeclToDeclareForBlock; 1548e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff VarDecl *GlobalVarDecl; 1551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 156b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff bool DisableReplaceStmt; 1571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 158545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian static const int OBJC_ABI_VERSION =7 ; 15977cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner public: 160e3a6198400453c0d9623207718e4942f7c111f87Ted Kremenek virtual void Initialize(ASTContext &context); 161e3a6198400453c0d9623207718e4942f7c111f87Ted Kremenek 162f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Top Level Driver code. 163682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner virtual void HandleTopLevelDecl(DeclGroupRef D) { 164682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) 165682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner HandleTopLevelSingleDecl(*I); 166682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner } 167682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner void HandleTopLevelSingleDecl(Decl *D); 1682c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner void HandleDeclInMainFile(Decl *D); 16966d6f048471aad6daf67b3ea804b54fbea72a076Eli Friedman RewriteObjC(std::string inFile, llvm::raw_ostream *OS, 170c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman Diagnostic &D, const LangOptions &LOpts, 171c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool silenceMacroWarn); 172e452e0ffc81c6c3d79680f552f2623e6cf0956d7Ted Kremenek 173e452e0ffc81c6c3d79680f552f2623e6cf0956d7Ted Kremenek ~RewriteObjC() {} 1741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 175dacbc5d46aaeea817742b8c76c987b87d2490c85Chris Lattner virtual void HandleTranslationUnit(ASTContext &C); 1761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17788906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanian void ReplaceStmt(Stmt *Old, Stmt *New) { 1784c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff Stmt *ReplacingStmt = ReplacedNodes[Old]; 1791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1804c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff if (ReplacingStmt) 1814c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff return; // We can't rewrite the same node twice. 1824c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff 183b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (DisableReplaceStmt) 184b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; // Used when rewriting the assignment of a property setter. 185b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 186f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner // If replacement succeeded or warning disabled return with no warning. 18788906cddbb1d5b3a868eeeec6cb170befc829c2fFariborz Jahanian if (!Rewrite.ReplaceStmt(Old, New)) { 1884c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff ReplacedNodes[Old] = New; 1894c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff return; 1904c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff } 1914c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff if (SilenceRewriteMacroWarning) 192dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner return; 1930a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 1940a14eee528a901c16f0e288fbc10a3abc1660d87Chris Lattner << Old->getSourceRange(); 195dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner } 196b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 197b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { 198b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // Measaure the old text. 199b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff int Size = Rewrite.getRangeSize(SrcRange); 200b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (Size == -1) { 201b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 202b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff << Old->getSourceRange(); 203b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 204b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 205b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // Get the new text. 206b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff std::string SStr; 207b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff llvm::raw_string_ostream S(SStr); 208e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts)); 209b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff const std::string &Str = S.str(); 210b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 211b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // If replacement succeeded or warning disabled return with no warning. 212d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) { 213b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff ReplacedNodes[Old] = New; 214b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 215b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 216b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff if (SilenceRewriteMacroWarning) 217b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return; 218b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 219b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff << Old->getSourceRange(); 220b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff } 221b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff 222d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer void InsertText(SourceLocation Loc, llvm::StringRef Str, 223ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff bool InsertAfter = true) { 224aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner // If insertion succeeded or warning disabled return with no warning. 225d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer if (!Rewrite.InsertText(Loc, Str, InsertAfter) || 226f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner SilenceRewriteMacroWarning) 227f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner return; 2281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 229f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 230f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner } 2311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 232aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner void RemoveText(SourceLocation Loc, unsigned StrLen) { 233aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner // If removal succeeded or warning disabled return with no warning. 234aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner if (!Rewrite.RemoveText(Loc, StrLen) || SilenceRewriteMacroWarning) 235aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner return; 2361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 237aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 238aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner } 239f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 240aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner void ReplaceText(SourceLocation Start, unsigned OrigLength, 241d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer llvm::StringRef Str) { 242aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner // If removal succeeded or warning disabled return with no warning. 243d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer if (!Rewrite.ReplaceText(Start, OrigLength, Str) || 244aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner SilenceRewriteMacroWarning) 245aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner return; 2461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 247aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); 248aadaf78d65daef3ac1b45e4ad6136ce859962fe2Chris Lattner } 2491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 250f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Syntactic Rewriting. 251ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff void RewritePrologue(SourceLocation Loc); 252452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian void RewriteInclude(); 253f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner void RewriteTabs(); 254a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteForwardClassDecl(ObjCClassDecl *Dcl); 255a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 256a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCImplementationDecl *IMD, 257a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCCategoryImplDecl *CID); 258a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); 2594afa39deaa245592977136d367251ee2c173dd8dDouglas Gregor void RewriteImplementationDecl(Decl *Dcl); 260a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr); 2617c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian void RewriteTypeIntoString(QualType T, std::string &ResultStr, 2627c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *&FPRetType); 263a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian void RewriteByRefString(std::string &ResultStr, const std::string &Name, 264a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ValueDecl *VD); 265a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); 266a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); 267a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl); 268a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteMethodDeclaration(ObjCMethodDecl *Method); 2696327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff void RewriteProperty(ObjCPropertyDecl *prop); 27009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff void RewriteFunctionDecl(FunctionDecl *FD); 271fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar void RewriteBlockPointerType(std::string& Str, QualType Type); 272fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD); 273abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); 274a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); 2754c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian void RewriteTypeOfDecl(VarDecl *VD); 2764f95b750534f2111f28434b282bcbd5656002816Steve Naroff void RewriteObjCQualifiedInterfaceTypes(Expr *E); 277d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff bool needToScanForQualifiers(QualType T); 278d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian bool isSuperReceiver(Expr *recExpr); 279874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType getSuperStructType(); 280d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff QualType getConstantStringStructType(); 2811f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType convertFunctionTypeOfBlocks(const FunctionType *FT); 282baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); 2831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 284f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Expression Rewriting. 285f3473a7e48dfaaa88f58dd9304856e16754f9b1cSteve Naroff Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); 286c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff void CollectPropertySetters(Stmt *S); 2871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2888599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff Stmt *CurrentBody; 2898599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff ParentMap *PropParentMap; // created lazily. 2901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 291e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); 2922b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart, 2932b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian bool &replaced); 2942b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced); 295c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr); 2961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, 297b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff SourceRange SrcRange); 298b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); 299e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); 300beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); 30136ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); 302b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void WarnAboutReturnGotoStmts(Stmt *S); 303b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void HasReturnStmts(Stmt *S, bool &hasReturns); 304b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void RewriteTryReturnStmts(Stmt *S); 305b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff void RewriteSyncReturnStmts(Stmt *S, std::string buf); 306a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); 307a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); 308a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S); 309a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Stmt *RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S); 310a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); 311338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 312338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner SourceLocation OrigEnd); 3131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 3141d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Expr **args, unsigned nargs, 3151d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation StartLoc=SourceLocation(), 3161d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc=SourceLocation()); 3171d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, 3181d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation StartLoc=SourceLocation(), 3191d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc=SourceLocation()); 320e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmt *RewriteBreakStmt(BreakStmt *S); 321e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmt *RewriteContinueStmt(ContinueStmt *S); 32233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian void SynthCountByEnumWithState(std::string &buf); 3231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff void SynthMsgSendFunctionDecl(); 325874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff void SynthMsgSendSuperFunctionDecl(); 32680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian void SynthMsgSendStretFunctionDecl(); 327acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian void SynthMsgSendFpretFunctionDecl(); 32880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian void SynthMsgSendSuperStretFunctionDecl(); 32909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff void SynthGetClassFunctionDecl(); 3309bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff void SynthGetMetaClassFunctionDecl(); 331d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian void SynthGetSuperClassFunctionDecl(); 332a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian void SynthSelGetUidFunctionDecl(); 333c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff void SynthSuperContructorFunctionDecl(); 3341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 335f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Metadata emission. 336a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 337ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian std::string &Result); 3381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 339a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 340ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian std::string &Result); 3411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 342653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor template<typename MethodIterator> 343653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 344653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor MethodIterator MethodEnd, 3458e991ba2e256e56959a65a049e161aa30b3c0decFariborz Jahanian bool IsInstanceMethod, 3462e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian const char *prefix, 347158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner const char *ClassName, 348158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner std::string &Result); 3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 350621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 351621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff const char *prefix, 352621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff const char *ClassName, 353621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string &Result); 354621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, 3551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const char *prefix, 356621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff const char *ClassName, 357621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string &Result); 358a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, 35926e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result); 3607c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian void SynthesizeIvarOffsetComputation(ObjCContainerDecl *IDecl, 3611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ObjCIvarDecl *ivar, 36226e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result); 363ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff void RewriteImplementations(); 364ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff void SynthesizeMetaDataIntoBuffer(std::string &Result); 3651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36654055232a5ddb9529726e934301b125cb720a273Steve Naroff // Block rewriting. 3671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); 36854055232a5ddb9529726e934301b125cb720a273Steve Naroff void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); 3691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37054055232a5ddb9529726e934301b125cb720a273Steve Naroff void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); 37154055232a5ddb9529726e934301b125cb720a273Steve Naroff void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); 3721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Block specific rewrite rules. 37454055232a5ddb9529726e934301b125cb720a273Steve Naroff void RewriteBlockCall(CallExpr *Exp); 37554055232a5ddb9529726e934301b125cb720a273Steve Naroff void RewriteBlockPointerDecl(NamedDecl *VD); 37652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian void RewriteByRefVar(VarDecl *VD); 377ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); 378f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian Stmt *RewriteBlockDeclRefExpr(Expr *VD); 3796cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); 38054055232a5ddb9529726e934301b125cb720a273Steve Naroff void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); 3811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 38354055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *funcName, std::string Tag); 3841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string SynthesizeBlockFunc(BlockExpr *CE, int i, 38554055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *funcName, std::string Tag); 38601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string SynthesizeBlockImpl(BlockExpr *CE, 38701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string Tag, std::string Desc); 38801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string SynthesizeBlockDescriptor(std::string DescTag, 38901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string ImplTag, 39001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff int i, const char *funcName, 39101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff unsigned hasCopy); 3928a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); 39354055232a5ddb9529726e934301b125cb720a273Steve Naroff void SynthesizeBlockLiterals(SourceLocation FunLocStart, 394abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian const char *FunName); 3953d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff void RewriteRecordBody(RecordDecl *RD); 3961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39754055232a5ddb9529726e934301b125cb720a273Steve Naroff void CollectBlockDeclRefInfo(BlockExpr *Exp); 39854055232a5ddb9529726e934301b125cb720a273Steve Naroff void GetBlockDeclRefExprs(Stmt *S); 3995e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian void GetInnerBlockDeclRefExprs(Stmt *S, 4005e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs, 40172952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts); 4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 40354055232a5ddb9529726e934301b125cb720a273Steve Naroff // We avoid calling Type::isBlockPointerType(), since it operates on the 40454055232a5ddb9529726e934301b125cb720a273Steve Naroff // canonical type. We only care if the top-level type is a closure pointer. 4058189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek bool isTopLevelBlockPointerType(QualType T) { 4068189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek return isa<BlockPointerType>(T); 4078189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek } 4081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4094fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// convertBlockPointerToFunctionPointer - Converts a block-pointer type 4104fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// to a function pointer type and upon success, returns true; false 4114fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian /// otherwise. 4124fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian bool convertBlockPointerToFunctionPointer(QualType &T) { 4134fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (isTopLevelBlockPointerType(T)) { 4144fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian const BlockPointerType *BPT = T->getAs<BlockPointerType>(); 4154fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian T = Context->getPointerType(BPT->getPointeeType()); 4164fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian return true; 4174fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian } 4184fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian return false; 4194fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian } 4204fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian 42154055232a5ddb9529726e934301b125cb720a273Steve Naroff // FIXME: This predicate seems like it would be useful to add to ASTContext. 42254055232a5ddb9529726e934301b125cb720a273Steve Naroff bool isObjCType(QualType T) { 42354055232a5ddb9529726e934301b125cb720a273Steve Naroff if (!LangOpts.ObjC1 && !LangOpts.ObjC2) 42454055232a5ddb9529726e934301b125cb720a273Steve Naroff return false; 4251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 42654055232a5ddb9529726e934301b125cb720a273Steve Naroff QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); 4271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 42854055232a5ddb9529726e934301b125cb720a273Steve Naroff if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || 42954055232a5ddb9529726e934301b125cb720a273Steve Naroff OCT == Context->getCanonicalType(Context->getObjCClassType())) 43054055232a5ddb9529726e934301b125cb720a273Steve Naroff return true; 4311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4326217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (const PointerType *PT = OCT->getAs<PointerType>()) { 4331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (isa<ObjCInterfaceType>(PT->getPointeeType()) || 434d1b3c2dd5bc1f3103bee6137957aa7c5f8f2f0bcSteve Naroff PT->getPointeeType()->isObjCQualifiedIdType()) 43554055232a5ddb9529726e934301b125cb720a273Steve Naroff return true; 43654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 43754055232a5ddb9529726e934301b125cb720a273Steve Naroff return false; 43854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 43954055232a5ddb9529726e934301b125cb720a273Steve Naroff bool PointerTypeTakesAnyBlockArguments(QualType QT); 4408189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek void GetExtentOfArgList(const char *Name, const char *&LParen, 4418189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek const char *&RParen); 442b2f9e516327310d95840d442416084508f80c183Steve Naroff void RewriteCastExpr(CStyleCastExpr *CE); 4431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 444fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff FunctionDecl *SynthBlockInitFunctionDecl(const char *name); 4455e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian Stmt *SynthBlockInitExpr(BlockExpr *Exp, 4465e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian const llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs); 4471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 448621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff void QuoteDoublequotes(std::string &From, std::string &To) { 4491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (unsigned i = 0; i < From.length(); i++) { 450621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (From[i] == '"') 451621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff To += "\\\""; 452621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 453621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff To += From[i]; 454621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 455621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 45677cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner }; 4579d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall 4589d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall // Helper function: create a CStyleCastExpr with trivial type source info. 4599d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, 4609d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CastKind Kind, Expr *E) { 4619d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); 46241b2dcd465f1e438502c420effc9d0c747f9db8fAnders Carlsson return new (Ctx) CStyleCastExpr(Ty, Kind, E, CXXBaseSpecifierArray(), TInfo, 4639d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall SourceLocation(), SourceLocation()); 4649d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall } 46577cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner} 46677cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 4671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, 4681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump NamedDecl *D) { 46972564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor if (FunctionProtoType *fproto = dyn_cast<FunctionProtoType>(funcType)) { 4701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), 47154055232a5ddb9529726e934301b125cb720a273Steve Naroff E = fproto->arg_type_end(); I && (I != E); ++I) 47201f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(*I)) { 47354055232a5ddb9529726e934301b125cb720a273Steve Naroff // All the args are checked/rewritten. Don't call twice! 47454055232a5ddb9529726e934301b125cb720a273Steve Naroff RewriteBlockPointerDecl(D); 47554055232a5ddb9529726e934301b125cb720a273Steve Naroff break; 47654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 47754055232a5ddb9529726e934301b125cb720a273Steve Naroff } 47854055232a5ddb9529726e934301b125cb720a273Steve Naroff} 47954055232a5ddb9529726e934301b125cb720a273Steve Naroff 48054055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { 4816217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek const PointerType *PT = funcType->getAs<PointerType>(); 48254055232a5ddb9529726e934301b125cb720a273Steve Naroff if (PT && PointerTypeTakesAnyBlockArguments(funcType)) 48372564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); 48454055232a5ddb9529726e934301b125cb720a273Steve Naroff} 48554055232a5ddb9529726e934301b125cb720a273Steve Naroff 486b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanianstatic bool IsHeaderFile(const std::string &Filename) { 487b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian std::string::size_type DotPos = Filename.rfind('.'); 4881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 489b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian if (DotPos == std::string::npos) { 490b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // no file extension 4911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return false; 492b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian } 4931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 494b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); 495b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // C header: .h 496b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian // C++ header: .hh or .H; 497b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian return Ext == "h" || Ext == "hh" || Ext == "H"; 4981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump} 499b4b2f0c9e80c6613c3e9846da121632ea39bcd5dFariborz Jahanian 50066d6f048471aad6daf67b3ea804b54fbea72a076Eli FriedmanRewriteObjC::RewriteObjC(std::string inFile, llvm::raw_ostream* OS, 501c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman Diagnostic &D, const LangOptions &LOpts, 502c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool silenceMacroWarn) 503c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS), 504c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman SilenceRewriteMacroWarning(silenceMacroWarn) { 505a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff IsHeader = IsHeaderFile(inFile); 5061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning, 507a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff "rewriting sub-expression within a macro (may not be correct)"); 5081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning, 5098189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek "rewriter doesn't support user-specified control flow semantics " 5108189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek "for @try/@finally (code may not execute properly)"); 511a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff} 512a7b402dc258bf38ab5e206dbf4916a69d3ee3cc8Steve Naroff 513bce831b1ecda51cd1abd3c07467294ffd21f5f86Eli FriedmanASTConsumer *clang::CreateObjCRewriter(const std::string& InFile, 514bce831b1ecda51cd1abd3c07467294ffd21f5f86Eli Friedman llvm::raw_ostream* OS, 5151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diagnostic &Diags, 516c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman const LangOptions &LOpts, 517c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman bool SilenceRewriteMacroWarning) { 518c6d656e2b0491f224ddd48507627b51d630d749aEli Friedman return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); 519e365c50a21cb02e0219433db0c4461566ad4a597Chris Lattner} 52077cd2a0b6eea81cc393b4c9e2941ec31fa09fdbeChris Lattner 521b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::Initialize(ASTContext &context) { 5229e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner Context = &context; 5239e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SM = &Context->getSourceManager(); 524ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis TUDecl = Context->getTranslationUnitDecl(); 5259e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendFunctionDecl = 0; 5269e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendSuperFunctionDecl = 0; 5279e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendStretFunctionDecl = 0; 5289e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendSuperStretFunctionDecl = 0; 5299e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MsgSendFpretFunctionDecl = 0; 5309e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner GetClassFunctionDecl = 0; 5319e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner GetMetaClassFunctionDecl = 0; 532d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian GetSuperClassFunctionDecl = 0; 5339e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SelGetUidFunctionDecl = 0; 5349e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner CFStringFunctionDecl = 0; 5359e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner ConstantStringClassReference = 0; 5369e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner NSStringRecord = 0; 53754055232a5ddb9529726e934301b125cb720a273Steve Naroff CurMethodDef = 0; 53854055232a5ddb9529726e934301b125cb720a273Steve Naroff CurFunctionDef = 0; 539abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 540b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff GlobalVarDecl = 0; 5419e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner SuperStructDecl = 0; 542621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolTypeDecl = 0; 5439630ec5b6785e5b6e1c71aeddcad05005beb7483Steve Naroff ConstantStringDecl = 0; 5449e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner BcLabelCount = 0; 545c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff SuperContructorFunctionDecl = 0; 546d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff NumObjCStringLiterals = 0; 54768272b86b36f89d7ceba1ec9a2826c2126adc72eSteve Naroff PropParentMap = 0; 54868272b86b36f89d7ceba1ec9a2826c2126adc72eSteve Naroff CurrentBody = 0; 549b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff DisableReplaceStmt = false; 550f292fcf6bd5118499a830e0950429effeb373c28Fariborz Jahanian objc_impl_method = false; 5511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5529e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner // Get the ID and start/end of the main file. 5539e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileID = SM->getMainFileID(); 5549e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID); 5559e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileStart = MainBuf->getBufferStart(); 5569e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner MainFileEnd = MainBuf->getBufferEnd(); 5571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5582c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions()); 5591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5609e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner // declaring objc_selector outside the parameter list removes a silly 5619e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner // scope related warning... 562ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff if (IsHeader) 56362c2632c555bc701d41f0eb1803bbf0660d7f0c0Steve Naroff Preamble = "#pragma once\n"; 564ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "struct objc_selector; struct objc_class;\n"; 56546a98a7df016b4a6835a1902c2f8ff2a3a8012baSteve Naroff Preamble += "struct __rw_objc_super { struct objc_object *object; "; 566ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "struct objc_object *superClass; "; 567c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff if (LangOpts.Microsoft) { 568c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff // Add a constructor for creating temporary objects. 5698189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) " 5708189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ": "; 571ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "object(o), superClass(s) {} "; 572c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff } 573ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "};\n"; 574ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; 575ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "typedef struct objc_object Protocol;\n"; 576ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#define _REWRITER_typedef_Protocol\n"; 577ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#endif\n"; 5784ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff if (LangOpts.Microsoft) { 5794ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; 5804ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; 5814ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff } else 5827c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; 5834ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend"; 584ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5854ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper"; 586ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 5874ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend_stret"; 588ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5894ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper_stret"; 590ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; 5914ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret"; 592ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; 5934ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass"; 594ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(const char *);\n"; 595d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; 596d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian Preamble += "(struct objc_class *);\n"; 5974ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass"; 598ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "(const char *);\n"; 5994ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n"; 6004ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n"; 6014ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n"; 6024ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n"; 6034ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match"; 604580ca7859330f8c92a66b09c21399ed9efa3991eSteve Naroff Preamble += "(struct objc_class *, struct objc_object *);\n"; 60559f05a48a7b0353090da2b8f878c2d760e55731cSteve Naroff // @synchronized hooks. 6064ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n"; 6074ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n"; 6084ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; 609ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; 610ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "struct __objcFastEnumerationState {\n\t"; 611ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "unsigned long state;\n\t"; 612b10f273eb60db2f2205b955fe4f7a43e09a5e2f2Steve Naroff Preamble += "void **itemsPtr;\n\t"; 613ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "unsigned long *mutationsPtr;\n\t"; 614ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "unsigned long extra[5];\n};\n"; 6154ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; 616ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#define __FASTENUMERATIONSTATE\n"; 617ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#endif\n"; 618ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; 619ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "struct __NSConstantStringImpl {\n"; 620ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " int *isa;\n"; 621ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " int flags;\n"; 622ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " char *str;\n"; 623ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " long length;\n"; 624ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "};\n"; 62588bee7451399c04b7e1c49cdeb16fadf0dd66f58Steve Naroff Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; 62688bee7451399c04b7e1c49cdeb16fadf0dd66f58Steve Naroff Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; 62788bee7451399c04b7e1c49cdeb16fadf0dd66f58Steve Naroff Preamble += "#else\n"; 6284ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; 62988bee7451399c04b7e1c49cdeb16fadf0dd66f58Steve Naroff Preamble += "#endif\n"; 630ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; 631ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "#endif\n"; 63254055232a5ddb9529726e934301b125cb720a273Steve Naroff // Blocks preamble. 63354055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "#ifndef BLOCK_IMPL\n"; 63454055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "#define BLOCK_IMPL\n"; 63554055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "struct __block_impl {\n"; 63654055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += " void *isa;\n"; 63754055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += " int Flags;\n"; 63801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Preamble += " int Reserved;\n"; 63954055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += " void *FuncPtr;\n"; 64054055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "};\n"; 6415bc60d0c324a1b3984cd4a32acb587c8f873ab5fSteve Naroff Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; 642c9c1e9c4b513e83146eff1728142683980df26a7Steve Naroff Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; 6437c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Preamble += "extern \"C\" __declspec(dllexport) " 6447c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian "void _Block_object_assign(void *, const void *, const int);\n"; 645a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; 646a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; 647a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; 648a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "#else\n"; 649cd826370bb146a25bddea48399953dd3077710cfSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; 650cd826370bb146a25bddea48399953dd3077710cfSteve Naroff Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; 651a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; 652a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; 653a851e60b7eb1d51549222ac838b8b602f23ec701Steve Naroff Preamble += "#endif\n"; 65454055232a5ddb9529726e934301b125cb720a273Steve Naroff Preamble += "#endif\n"; 655a48396e10f75966ed5ca974dcc73907ce8c80deeSteve Naroff if (LangOpts.Microsoft) { 6564ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; 6574ebd716f260584663297bdb820714788f2a1e4cbSteve Naroff Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; 658553e583e1d30fe30ac2de3526536bbebee6da1ceChris Lattner Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. 659a48396e10f75966ed5ca974dcc73907ce8c80deeSteve Naroff Preamble += "#define __attribute__(X)\n"; 660553e583e1d30fe30ac2de3526536bbebee6da1ceChris Lattner Preamble += "#endif\n"; 66134204195de802e9d3cc8d54355b2ad4b3c27f188Fariborz Jahanian Preamble += "#define __weak\n"; 662a48396e10f75966ed5ca974dcc73907ce8c80deeSteve Naroff } 6632086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian else { 66452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian Preamble += "#define __block\n"; 6652086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian Preamble += "#define __weak\n"; 6662086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian } 667df496529b7009d6e58f335926884200b38d27687Fariborz Jahanian // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long 668df496529b7009d6e58f335926884200b38d27687Fariborz Jahanian // as this avoids warning in any 64bit/32bit compilation model. 669df496529b7009d6e58f335926884200b38d27687Fariborz Jahanian Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; 6709e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner} 6719e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner 6729e13c2eb681b5d8e14f930b14300caaae22fdb92Chris Lattner 673f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 674f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner// Top Level Driver Code 675f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 676f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 677682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattnervoid RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { 678e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek if (Diags.hasErrorOccurred()) 679e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek return; 680e50187a987dadb6a3b6f673125617c8f42ff3560Ted Kremenek 6812c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // Two cases: either the decl could be in the main file, or it could be in a 6822c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // #included file. If the former, rewrite it now. If the later, check to see 6832c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // if we rewrote the #include/#import. 6842c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner SourceLocation Loc = D->getLocation(); 685f7cf85b330bedd2877e1371fb0a83e99751ae162Chris Lattner Loc = SM->getInstantiationLoc(Loc); 6861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 6872c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner // If this is for a builtin, ignore it. 6882c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner if (Loc.isInvalid()) return; 6892c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner 690ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Look for built-in declarations that we need to refer during the rewrite. 691ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 69209b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff RewriteFunctionDecl(FD); 693248a753f6b670692523c99afaeb8fe98f7ae3ca7Steve Naroff } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) { 694beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff // declared in <Foundation/NSString.h> 6958ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner if (strcmp(FVD->getNameAsCString(), "_NSConstantStringClassReference") == 0) { 696beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff ConstantStringClassReference = FVD; 697beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff return; 698beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff } 699a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) { 700bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff RewriteInterfaceDecl(MD); 701a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { 702423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff RewriteCategoryDecl(CD); 703a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { 704752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff RewriteProtocolDecl(PD); 7051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } else if (ObjCForwardProtocolDecl *FP = 706a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek dyn_cast<ObjCForwardProtocolDecl>(D)){ 707d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian RewriteForwardProtocolDecl(FP); 708d04341000d35c8808a72838b057eed7bf13b7661Douglas Gregor } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { 709d04341000d35c8808a72838b057eed7bf13b7661Douglas Gregor // Recurse into linkage specifications 71017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis for (DeclContext::decl_iterator DI = LSD->decls_begin(), 71117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis DIEnd = LSD->decls_end(); 712d04341000d35c8808a72838b057eed7bf13b7661Douglas Gregor DI != DIEnd; ++DI) 713682bf92db408a6cbc3d37b5496a99b6ef85041ecChris Lattner HandleTopLevelSingleDecl(*DI); 714ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff } 715f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // If we have a decl in the main file, see if we should rewrite it. 716cf7e958483735935de6e0a64aa1e55a967116303Ted Kremenek if (SM->isFromMainFile(Loc)) 7172c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner return HandleDeclInMainFile(D); 7182c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner} 7192c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner 720f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 721f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner// Syntactic (non-AST) Rewriting Code 722f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner//===----------------------------------------------------------------------===// 723f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 724b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteInclude() { 7252b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); 726f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer llvm::StringRef MainBuf = SM->getBufferData(MainFileID); 727f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer const char *MainBufStart = MainBuf.begin(); 728f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer const char *MainBufEnd = MainBuf.end(); 729452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian size_t ImportLen = strlen("import"); 7301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 731af57b46f12e9dd48485fa27f2088f85466ee9292Fariborz Jahanian // Loop over the whole file, looking for includes. 732452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { 733452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (*BufPtr == '#') { 734452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (++BufPtr == MainBufEnd) 735452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian return; 736452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian while (*BufPtr == ' ' || *BufPtr == '\t') 737452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (++BufPtr == MainBufEnd) 738452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian return; 739452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian if (!strncmp(BufPtr, "import", ImportLen)) { 740452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian // replace import with include 7411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation ImportLoc = 742452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian LocStart.getFileLocWithOffset(BufPtr-MainBufStart); 743d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(ImportLoc, ImportLen, "include"); 744452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian BufPtr += ImportLen; 745452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 746452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 747452b899c9f5fbcb8ddd130375b7982bed6b4d93fFariborz Jahanian } 7488a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner} 7498a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 750b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteTabs() { 751f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer llvm::StringRef MainBuf = SM->getBufferData(MainFileID); 752f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer const char *MainBufStart = MainBuf.begin(); 753f6ac97b101c8840efa92bf29166077ce4049e293Benjamin Kramer const char *MainBufEnd = MainBuf.end(); 7541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 755f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Loop over the whole file, looking for tabs. 756f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) { 757f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner if (*BufPtr != '\t') 758f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner continue; 7591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 760f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Okay, we found a tab. This tab will turn into at least one character, 761f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // but it depends on which 'virtual column' it is in. Compute that now. 762f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner unsigned VCol = 0; 763f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' && 764f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r') 765f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner ++VCol; 7661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 767f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Okay, now that we know the virtual column, we know how many spaces to 768f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // insert. We assume 8-character tab-stops. 769f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner unsigned Spaces = 8-(VCol & 7); 7701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 771f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Get the location of the tab. 7722b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner SourceLocation TabLoc = SM->getLocForStartOfFile(MainFileID); 7732b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart); 7741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 775f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Rewrite the single tab character into a sequence of spaces. 776d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(TabLoc, 1, llvm::StringRef(" ", Spaces)); 777f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner } 7782c64b7b9381be4ff62fbdc404ed3f14c8086898dChris Lattner} 7798a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 780eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroffstatic std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl, 781eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff ObjCIvarDecl *OID) { 782eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff std::string S; 783eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S = "((struct "; 784eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S += ClassDecl->getIdentifier()->getName(); 785eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff S += "_IMPL *)self)->"; 7865ffe14ca96bd662de7820f6875d3f04789a640c1Daniel Dunbar S += OID->getName(); 787eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return S; 788eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff} 789eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff 790a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroffvoid RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 791a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCImplementationDecl *IMD, 792a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff ObjCCategoryImplDecl *CID) { 7937c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian static bool objcGetPropertyDefined = false; 7947c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian static bool objcSetPropertyDefined = false; 795d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff SourceLocation startLoc = PID->getLocStart(); 796d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, "// "); 797eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 798eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff assert((*startBuf == '@') && "bogus @synthesize location"); 799eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 800eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff assert((*semiBuf == ';') && "@synthesize: can't find ';'"); 8018189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek SourceLocation onePastSemiLoc = 8028189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek startLoc.getFileLocWithOffset(semiBuf-startBuf+1); 803eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff 804eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 805eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return; // FIXME: is this correct? 8061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 807eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff // Generate the 'getter' function. 808eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff ObjCPropertyDecl *PD = PID->getPropertyDecl(); 809eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff ObjCInterfaceDecl *ClassDecl = PD->getGetterMethodDecl()->getClassInterface(); 810eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); 8111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 812dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff if (!OID) 813dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff return; 8147c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian unsigned Attributes = PD->getPropertyAttributes(); 8157c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) && 8167c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian (Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 8177c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_copy)); 818dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff std::string Getr; 8197c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (GenGetProperty && !objcGetPropertyDefined) { 8207c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian objcGetPropertyDefined = true; 8217c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian // FIXME. Is this attribute correct in all cases? 8227c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr = "\nextern \"C\" __declspec(dllimport) " 8237c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian "id objc_getProperty(id, SEL, long, bool);\n"; 8247c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 825dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff RewriteObjCMethodDecl(PD->getGetterMethodDecl(), Getr); 826dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff Getr += "{ "; 827dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff // Synthesize an explicit cast to gain access to the ivar. 8283539cdb98b1132d30795f932920ff1c90f94b4e8Steve Naroff // See objc-act.c:objc_synthesize_new_getter() for details. 8297c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (GenGetProperty) { 8307c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) 8317c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += "typedef "; 8327c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *FPRetType = 0; 8337c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr, 8347c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian FPRetType); 8357c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += " _TYPE"; 8367c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (FPRetType) { 8377c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += ")"; // close the precedence "scope" for "*". 8387c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 8397c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian // Now, emit the argument types (if any). 840fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){ 8417c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += "("; 8427c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 8437c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (i) Getr += ", "; 844fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string ParamStr = FT->getArgType(i).getAsString( 845fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar Context->PrintingPolicy); 8467c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += ParamStr; 8477c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8487c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (FT->isVariadic()) { 8497c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (FT->getNumArgs()) Getr += ", "; 8507c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += "..."; 8517c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8527c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += ")"; 8537c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } else 8547c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += "()"; 8557c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8567c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += ";\n"; 8577c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += "return (_TYPE)"; 8587c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += "objc_getProperty(self, _cmd, "; 8597c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian SynthesizeIvarOffsetComputation(ClassDecl, OID, Getr); 8607c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += ", 1)"; 8617c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8627c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else 8637c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Getr += "return " + getIvarAccessString(ClassDecl, OID); 864dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff Getr += "; }"; 865d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, Getr); 866eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff if (PD->isReadOnly()) 867eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff return; 8681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 869eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff // Generate the 'setter' function. 870eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff std::string Setr; 8717c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 8727c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian ObjCPropertyDecl::OBJC_PR_copy); 8737c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (GenSetProperty && !objcSetPropertyDefined) { 8747c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian objcSetPropertyDefined = true; 8757c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian // FIXME. Is this attribute correct in all cases? 8767c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr = "\nextern \"C\" __declspec(dllimport) " 8777c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian "void objc_setProperty (id, SEL, long, id, bool, bool);\n"; 8787c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8797c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 880eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff RewriteObjCMethodDecl(PD->getSetterMethodDecl(), Setr); 881eb0646c8df1c5c8de62b622d13d0c9f19aa29277Steve Naroff Setr += "{ "; 882dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff // Synthesize an explicit cast to initialize the ivar. 88315f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff // See objc-act.c:objc_synthesize_new_setter() for details. 8847c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (GenSetProperty) { 8857c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "objc_setProperty (self, _cmd, "; 8867c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian SynthesizeIvarOffsetComputation(ClassDecl, OID, Setr); 8877c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += ", (id)"; 8887c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += PD->getNameAsCString(); 8897c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += ", "; 8907c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) 8917c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "0, "; 8927c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else 8937c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "1, "; 8947c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (Attributes & ObjCPropertyDecl::OBJC_PR_copy) 8957c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "1)"; 8967c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else 8977c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += "0)"; 8987c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 8997c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else { 9007c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += getIvarAccessString(ClassDecl, OID) + " = "; 9017c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian Setr += PD->getNameAsCString(); 9027c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian } 903dd2fdf13f11f93a8bd271807db25c71191914807Steve Naroff Setr += "; }"; 904d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, Setr); 905d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff} 9068a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner 907b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { 908f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Get the start location and compute the semi location. 909f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner SourceLocation startLoc = ClassDecl->getLocation(); 910f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner const char *startBuf = SM->getCharacterData(startLoc); 911f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner const char *semiPtr = strchr(startBuf, ';'); 9121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 913f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // Translate to typedef's that forward reference structs with the same name 914f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // as the class. As a convenience, we include the original declaration 915f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner // as a comment. 916f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner std::string typedefString; 91791fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian typedefString += "// @class "; 91891fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end(); 91991fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian I != E; ++I) { 92091fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian ObjCInterfaceDecl *ForwardDecl = I->getInterface(); 92191fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian typedefString += ForwardDecl->getNameAsString(); 92291fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian if (I+1 != E) 92391fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian typedefString += ", "; 92491fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian else 92591fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian typedefString += ";\n"; 92691fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian } 92791fbd12d8b6e60b72883ff4c42e2a0993087f876Fariborz Jahanian 92867956052ea5fb0cd7f443de96a11f9a0176dc681Chris Lattner for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end(); 92967956052ea5fb0cd7f443de96a11f9a0176dc681Chris Lattner I != E; ++I) { 930321c22f1c4271c3d9a3d4d3fc18847f948ab595bTed Kremenek ObjCInterfaceDecl *ForwardDecl = I->getInterface(); 93132174826f58d38c20f376fe64ceac4a278133883Steve Naroff typedefString += "#ifndef _REWRITER_typedef_"; 932d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner typedefString += ForwardDecl->getNameAsString(); 93332174826f58d38c20f376fe64ceac4a278133883Steve Naroff typedefString += "\n"; 93432174826f58d38c20f376fe64ceac4a278133883Steve Naroff typedefString += "#define _REWRITER_typedef_"; 935d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner typedefString += ForwardDecl->getNameAsString(); 93632174826f58d38c20f376fe64ceac4a278133883Steve Naroff typedefString += "\n"; 937352336bb0a480b044eb03e7359e73d3b173d9cddSteve Naroff typedefString += "typedef struct objc_object "; 938d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner typedefString += ForwardDecl->getNameAsString(); 93932174826f58d38c20f376fe64ceac4a278133883Steve Naroff typedefString += ";\n#endif\n"; 940934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff } 9411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 942934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Replace the @class with typedefs corresponding to the classes. 943d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); 944f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner} 945f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner 946b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { 947d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian // When method is a synthesized one, such as a getter/setter there is 948d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian // nothing to rewrite. 949d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian if (Method->isSynthesized()) 950d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian return; 95158dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff SourceLocation LocStart = Method->getLocStart(); 95258dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff SourceLocation LocEnd = Method->getLocEnd(); 9531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 95430fc933e5fbbb5f0ea60c47976d435254e378536Chris Lattner if (SM->getInstantiationLineNumber(LocEnd) > 95530fc933e5fbbb5f0ea60c47976d435254e378536Chris Lattner SM->getInstantiationLineNumber(LocStart)) { 956d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LocStart, "#if 0\n"); 957d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocEnd, 1, ";\n#endif\n"); 95858dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff } else { 959d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LocStart, "// "); 960423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff } 961423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff} 962423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff 9631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) { 964d0502407c1b41b2ace326f355d7b7a6876246223Fariborz Jahanian SourceLocation Loc = prop->getAtLoc(); 9651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 966d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(Loc, 0, "// "); 9676327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff // FIXME: handle properties that are declared across multiple lines. 968957cf65bf32fe7c84886a2296d0b4ede40029850Fariborz Jahanian} 969957cf65bf32fe7c84886a2296d0b4ede40029850Fariborz Jahanian 970b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { 971423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff SourceLocation LocStart = CatDecl->getLocStart(); 9721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 973423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff // FIXME: handle category headers that are declared across multiple lines. 974d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 9751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 97613751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), 97713751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian E = CatDecl->prop_end(); I != E; ++I) 97813751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian RewriteProperty(*I); 97913751e3edc7fe50b0ab4e0f5fe7501e81c83c795Fariborz Jahanian 9801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCCategoryDecl::instmeth_iterator 9811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); 9826ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 98358dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 9841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCCategoryDecl::classmeth_iterator 98517945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); 9866ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 98758dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 98858dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 989423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff // Lastly, comment out the @end. 99073d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(CatDecl->getAtEndRange().getBegin(), 99173d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian strlen("@end"), "/* @end */"); 992423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff} 993423cb565abc681b770fb4b9b4bc24d398c98157bSteve Naroff 994b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { 995752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff SourceLocation LocStart = PDecl->getLocStart(); 9961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 997752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff // FIXME: handle protocol headers that are declared across multiple lines. 998d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 9991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCProtocolDecl::instmeth_iterator 10011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 10026ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 100358dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 10046ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor for (ObjCProtocolDecl::classmeth_iterator 100517945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 10066ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 100758dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 100858dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 1009752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff // Lastly, comment out the @end. 1010782f2f52b78d8ca785110398a7f7b56b830b9ac7Ted Kremenek SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); 101173d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(LocEnd, strlen("@end"), "/* @end */"); 10128cc764c67afc249628ba4f65b8e2d2ad461112ffSteve Naroff 1013b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian // Must comment out @optional/@required 1014b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 1015b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1016b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian for (const char *p = startBuf; p < endBuf; p++) { 1017b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { 10188cc764c67afc249628ba4f65b8e2d2ad461112ffSteve Naroff SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); 1019d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); 10201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1021b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1022b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { 10238cc764c67afc249628ba4f65b8e2d2ad461112ffSteve Naroff SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); 1024d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); 10251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1026b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1027b82b3ea8a12e4bc5960f59c1c2b9f483af5471e8Fariborz Jahanian } 1028752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff} 1029752d6ef8c886b4de3365efef15449cd6f939baf1Steve Naroff 1030b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) { 1031d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian SourceLocation LocStart = PDecl->getLocation(); 1032b7fa992be16668b61f722e6e125137216860469eSteve Naroff if (LocStart.isInvalid()) 1033b7fa992be16668b61f722e6e125137216860469eSteve Naroff assert(false && "Invalid SourceLocation"); 1034d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian // FIXME: handle forward protocol that are declared across multiple lines. 1035d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 0, "// "); 1036d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian} 1037d175ddfdbefff8646982dfd4afc5bdf6edbc9e67Fariborz Jahanian 10387c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanianvoid RewriteObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr, 10397c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *&FPRetType) { 10407c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian if (T->isObjCQualifiedIdType()) 1041c569249ca0ab755ac79d8cbbfcb2bcae19743624Fariborz Jahanian ResultStr += "id"; 10427c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian else if (T->isFunctionPointerType() || 10437c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian T->isBlockPointerType()) { 104476e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // needs special handling, since pointer-to-functions have special 104576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // syntax (where a decaration models use). 10467c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian QualType retType = T; 1047f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff QualType PointeeTy; 10486217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (const PointerType* PT = retType->getAs<PointerType>()) 1049f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff PointeeTy = PT->getPointeeType(); 10506217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) 1051f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff PointeeTy = BPT->getPointeeType(); 1052183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall if ((FPRetType = PointeeTy->getAs<FunctionType>())) { 1053fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += FPRetType->getResultType().getAsString( 1054fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar Context->PrintingPolicy); 1055f4312dc9b690fc79039560c125e9e3f8ea8a478eSteve Naroff ResultStr += "(*"; 105676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 105776e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } else 1058fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += T.getAsString(Context->PrintingPolicy); 10597c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian} 10607c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 10617c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanianvoid RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, 10627c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian std::string &ResultStr) { 10637c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian //fprintf(stderr,"In RewriteObjCMethodDecl\n"); 10647c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian const FunctionType *FPRetType = 0; 10657c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian ResultStr += "\nstatic "; 10667c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType); 1067531a1ea2f4c88817f3dc0f4628dfc34536f54c5eFariborz Jahanian ResultStr += " "; 10681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 106948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Unique method name 1070b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian std::string NameStr; 10711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1072f8d49f64ef6ab7e632717a31631fc289aab69428Douglas Gregor if (OMD->isInstanceMethod()) 1073b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_I_"; 107448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian else 1075b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_C_"; 10761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1077d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner NameStr += OMD->getClassInterface()->getNameAsString(); 1078b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_"; 10791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 10801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (ObjCCategoryImplDecl *CID = 10813e0a540b6d846178857289ec0eb8470a278d11a3Steve Naroff dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 1082d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner NameStr += CID->getNameAsString(); 1083b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += "_"; 108448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 10851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Append selector names, replacing ':' with '_' 1086077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner { 1087077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner std::string selString = OMD->getSelector().getAsString(); 108848a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian int len = selString.size(); 108948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian for (int i = 0; i < len; i++) 109048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian if (selString[i] == ':') 109148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian selString[i] = '_'; 1092b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian NameStr += selString; 109348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 1094b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian // Remember this name for metadata emission 1095b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian MethodInternalNames[OMD] = NameStr; 1096b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian ResultStr += NameStr; 10971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 109848a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Rewrite arguments 109948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += "("; 11001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 110148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // invisible arguments 1102f8d49f64ef6ab7e632717a31631fc289aab69428Douglas Gregor if (OMD->isInstanceMethod()) { 1103a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType selfTy = Context->getObjCInterfaceType(OMD->getClassInterface()); 110448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian selfTy = Context->getPointerType(selfTy); 110505b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff if (!LangOpts.Microsoft) { 110605b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff if (ObjCSynthesizedStructs.count(OMD->getClassInterface())) 110705b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff ResultStr += "struct "; 110805b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff } 110905b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff // When rewriting for Microsoft, explicitly omit the structure name. 1110d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += OMD->getClassInterface()->getNameAsString(); 111161ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff ResultStr += " *"; 111248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 111348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian else 1114fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += Context->getObjCClassType().getAsString( 1115fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar Context->PrintingPolicy); 11161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 111748a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += " self, "; 1118fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ResultStr += Context->getObjCSelType().getAsString(Context->PrintingPolicy); 111948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += " _cmd"; 11201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 112148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian // Method arguments. 112289951a86b594513c2a013532ed45d197413b1087Chris Lattner for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 112389951a86b594513c2a013532ed45d197413b1087Chris Lattner E = OMD->param_end(); PI != E; ++PI) { 112489951a86b594513c2a013532ed45d197413b1087Chris Lattner ParmVarDecl *PDecl = *PI; 112548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian ResultStr += ", "; 1126543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff if (PDecl->getType()->isObjCQualifiedIdType()) { 1127543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff ResultStr += "id "; 1128d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += PDecl->getNameAsString(); 1129543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff } else { 1130d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = PDecl->getNameAsString(); 11314fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian QualType QT = PDecl->getType(); 11324fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian // Make sure we convert "t (^)(...)" to "t (*)(...)". 11334fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (convertBlockPointerToFunctionPointer(QT)) 11344fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian QT.getAsStringInternal(Name, Context->PrintingPolicy); 11354fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian else 1136d249e1d1f1498b81314459ceda19d6ff25c278adDouglas Gregor PDecl->getType().getAsStringInternal(Name, Context->PrintingPolicy); 1137543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff ResultStr += Name; 1138543409e200234a1c97ea38b9d52bce22ff807080Steve Naroff } 113948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 11407c39ff7eb3dd7ae9b2b81cb66a139c9b52f47f1dFariborz Jahanian if (OMD->isVariadic()) 11417c39ff7eb3dd7ae9b2b81cb66a139c9b52f47f1dFariborz Jahanian ResultStr += ", ..."; 1142531a1ea2f4c88817f3dc0f4628dfc34536f54c5eFariborz Jahanian ResultStr += ") "; 11431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 114476e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FPRetType) { 114576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ")"; // close the precedence "scope" for "*". 11461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 114776e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff // Now, emit the argument types (if any). 114872564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { 114976e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "("; 115076e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 115176e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (i) ResultStr += ", "; 1152fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string ParamStr = FT->getArgType(i).getAsString( 1153fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar Context->PrintingPolicy); 115476e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ParamStr; 115576e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 115676e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FT->isVariadic()) { 115776e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff if (FT->getNumArgs()) ResultStr += ", "; 115876e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "..."; 115976e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 116076e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += ")"; 116176e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } else { 116276e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff ResultStr += "()"; 116376e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 116476e429d781a8871afb5050f39ab8e00e72bdf2f8Steve Naroff } 116548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian} 11664afa39deaa245592977136d367251ee2c173dd8dDouglas Gregorvoid RewriteObjC::RewriteImplementationDecl(Decl *OID) { 1167a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); 1168a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); 11691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1170a135216595c00ddb5ce5f5b853a3d1f4037a13b7Fariborz Jahanian InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// "); 11711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1172a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek for (ObjCCategoryImplDecl::instmeth_iterator 117317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), 117417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); 1175653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 117648a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian std::string ResultStr; 1177a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *OMD = *I; 1178a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCMethodDecl(OMD, ResultStr); 117948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian SourceLocation LocStart = OMD->getLocStart(); 11806fb0aee4f9dc261bbec72e1283ad8dc0557a6d96Argyrios Kyrtzidis SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 1181d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl 118248a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 118348a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1184d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, ResultStr); 118548a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 11861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1187a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek for (ObjCCategoryImplDecl::classmeth_iterator 118817945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), 118917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); 1190653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 119148a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian std::string ResultStr; 1192a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCMethodDecl *OMD = *I; 1193a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCMethodDecl(OMD, ResultStr); 119448a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian SourceLocation LocStart = OMD->getLocStart(); 11956fb0aee4f9dc261bbec72e1283ad8dc0557a6d96Argyrios Kyrtzidis SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 11961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 119748a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 119848a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 1199d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, ResultStr); 120048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian } 1201d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff for (ObjCCategoryImplDecl::propimpl_iterator 120217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), 12031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); 1204653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor I != E; ++I) { 1205a0876e88aff05e8fc0492d216c17bff16de31a37Steve Naroff RewritePropertyImplDecl(*I, IMD, CID); 1206d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff } 1207d40910b581b09c937a8c1fdcde9b8ec724398fb9Steve Naroff 1208d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// "); 120948a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian} 121048a0b6aa9d23bba2bd4ad943ad59106a91f8b3f7Fariborz Jahanian 1211b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 1212f908a87299d278164540f90b5b6e6cab7b14fb41Steve Naroff std::string ResultStr; 1213a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (!ObjCForwardDecls.count(ClassDecl)) { 12146c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff // we haven't seen a forward decl - generate a typedef. 12155086a8df9a269acc2e4f0deb1895d4a9e9d13f4dSteve Naroff ResultStr = "#ifndef _REWRITER_typedef_"; 1216d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 121732174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "\n"; 121832174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "#define _REWRITER_typedef_"; 1219d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 122032174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += "\n"; 122161ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff ResultStr += "typedef struct objc_object "; 1222d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ResultStr += ClassDecl->getNameAsString(); 122332174826f58d38c20f376fe64ceac4a278133883Steve Naroff ResultStr += ";\n#endif\n"; 12246c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff // Mark this typedef as having been generated. 1225a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCForwardDecls.insert(ClassDecl); 12266c6a2dbb4db96a69d6f1c2e3d322e4c3abd43814Steve Naroff } 1227a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek SynthesizeObjCInternalStruct(ClassDecl, ResultStr); 12281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), 123017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis E = ClassDecl->prop_end(); I != E; ++I) 12316327e0d55c590b3c2766fa76ef1db241a0467df2Steve Naroff RewriteProperty(*I); 12321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::instmeth_iterator 123317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); 12346ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 123558dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 12361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCInterfaceDecl::classmeth_iterator 12371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); 12386ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor I != E; ++I) 123958dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff RewriteMethodDeclaration(*I); 124058dbdeb69c063f82d644504fc638120198f7fad2Steve Naroff 12412feac5e559ca5c9693a3a19905ab106b9c52e193Steve Naroff // Lastly, comment out the @end. 124273d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), 124373d1eb064350d5310f0475366cbe54d2d1da27bbFariborz Jahanian "/* @end */"); 1244bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff} 1245bef1185418705e16012b3dd50cd7c260c8d6b79cSteve Naroff 1246b619d957b020744bb6bfdd1cef8169d8042df43eSteve NaroffStmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, 1247b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff SourceRange SrcRange) { 1248c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr. 1249c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // This allows us to reuse all the fun and games in SynthMessageExpr(). 1250c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS()); 1251c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff ObjCMessageExpr *MsgExpr; 1252c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff ObjCPropertyDecl *PDecl = PropRefExpr->getProperty(); 1253c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff llvm::SmallVector<Expr *, 1> ExprVec; 1254c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff ExprVec.push_back(newStmt); 12551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12568599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff Stmt *Receiver = PropRefExpr->getBase(); 12578599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver); 12588599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (PRE && PropGetters[PRE]) { 12598599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // This allows us to handle chain/nested property getters. 12608599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff Receiver = PropGetters[PRE]; 12618599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 126204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (isa<ObjCSuperExpr>(Receiver)) 126304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExpr = ObjCMessageExpr::Create(*Context, 126404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getType().getNonReferenceType(), 126504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME?*/SourceLocation(), 126604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Receiver->getLocStart(), 126704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*IsInstanceSuper=*/true, 126804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor cast<Expr>(Receiver)->getType(), 126904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getSetterName(), 127004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getSetterMethodDecl(), 127104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ExprVec[0], 1, 127204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME:*/SourceLocation()); 127304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor else 127404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExpr = ObjCMessageExpr::Create(*Context, 127504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getType().getNonReferenceType(), 127604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME: */SourceLocation(), 127704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor cast<Expr>(Receiver), 127804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getSetterName(), 127904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getSetterMethodDecl(), 128004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ExprVec[0], 1, 128104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME:*/SourceLocation()); 1282c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); 12831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1284c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // Now do the actual rewrite. 1285b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange); 1286e58ee0ca7cfad6ee75a088e7a6a090526e18da50Steve Naroff //delete BinOp; 12878189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references 12888189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // to things that stay around. 12898189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Context->Deallocate(MsgExpr); 1290c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff return ReplacingStmt; 129115f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff} 129215f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 1293c77a636688e188af7e7a9a05829e542adb48e880Steve NaroffStmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { 129415f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr. 129515f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff // This allows us to reuse all the fun and games in SynthMessageExpr(). 129615f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff ObjCMessageExpr *MsgExpr; 129715f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff ObjCPropertyDecl *PDecl = PropRefExpr->getProperty(); 12981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12998599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff Stmt *Receiver = PropRefExpr->getBase(); 13001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 13018599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver); 13028599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (PRE && PropGetters[PRE]) { 13038599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // This allows us to handle chain/nested property getters. 13048599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff Receiver = PropGetters[PRE]; 13058599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 130604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 130704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (isa<ObjCSuperExpr>(Receiver)) 130804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExpr = ObjCMessageExpr::Create(*Context, 130904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getType().getNonReferenceType(), 131004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME:*/SourceLocation(), 131104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Receiver->getLocStart(), 131204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*IsInstanceSuper=*/true, 131304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor cast<Expr>(Receiver)->getType(), 131404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getGetterName(), 131504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getGetterMethodDecl(), 131604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 0, 0, 131704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME:*/SourceLocation()); 131804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor else 131904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExpr = ObjCMessageExpr::Create(*Context, 132004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getType().getNonReferenceType(), 132104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME:*/SourceLocation(), 132204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor cast<Expr>(Receiver), 132304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getGetterName(), 132404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor PDecl->getGetterMethodDecl(), 132504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 0, 0, 132604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor /*FIXME:*/SourceLocation()); 132715f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 13284c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); 13298599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff 13308599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (!PropParentMap) 13318599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropParentMap = new ParentMap(CurrentBody); 13328599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff 13338599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff Stmt *Parent = PropParentMap->getParent(PropRefExpr); 13348599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (Parent && isa<ObjCPropertyRefExpr>(Parent)) { 13358599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // We stash away the ReplacingStmt since actually doing the 13368599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff // replacement/rewrite won't work for nested getters (e.g. obj.p.i) 13378599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropGetters[PropRefExpr] = ReplacingStmt; 13388189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references 13398189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // to things that stay around. 13408189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Context->Deallocate(MsgExpr); 13418599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff return PropRefExpr; // return the original... 13428599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } else { 13438599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff ReplaceStmt(PropRefExpr, ReplacingStmt); 13441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // delete PropRefExpr; elsewhere... 13458189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references 13468189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek // to things that stay around. 13478189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Context->Deallocate(MsgExpr); 13488599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff return ReplacingStmt; 13498599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 135015f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff} 135115f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff 13521eb4433ac451dc16f4133a88af2d002ac26c58efMike StumpStmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, 13532b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian SourceLocation OrigStart, 13542b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian bool &replaced) { 1355a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCIvarDecl *D = IV->getDecl(); 135684ed600154d48d75f204795410aae808d7e4b7bdFariborz Jahanian const Expr *BaseExpr = IV->getBase(); 135754055232a5ddb9529726e934301b125cb720a273Steve Naroff if (CurMethodDef) { 13588f0954309eb885891908ecdfbb06d720c63128edFariborz Jahanian if (BaseExpr->getType()->isObjCObjectPointerType()) { 13598189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ObjCInterfaceType *iFaceDecl = 136084ed600154d48d75f204795410aae808d7e4b7bdFariborz Jahanian dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 1361ffbdead156eb0bc94d1cc7e28eadcca52dfb8194Fariborz Jahanian assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); 1362f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff // lookup which class implements the instance variable. 1363f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff ObjCInterfaceDecl *clsDeclared = 0; 13641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 13656ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor clsDeclared); 1366f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 13671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1368f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff // Synthesize an explicit cast to gain access to the ivar. 1369f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff std::string RecName = clsDeclared->getIdentifier()->getName(); 1370f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff RecName += "_IMPL"; 1371d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer IdentifierInfo *II = &Context->Idents.get(RecName); 1372465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 1373df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek SourceLocation(), II); 1374f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 1375f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 13769d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 13779d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, 13789d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall IV->getBase()); 1379f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff // Don't forget the parens to enforce the proper binding. 13808189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), 13818189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek IV->getBase()->getLocEnd(), 13828189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek castExpr); 13832b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian replaced = true; 13841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (IV->isFreeIvar() && 138554055232a5ddb9529726e934301b125cb720a273Steve Naroff CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) { 13868189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek MemberExpr *ME = new (Context) MemberExpr(PE, true, D, 13878189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek IV->getLocation(), 13888189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek D->getType()); 13894c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // delete IV; leak for now, see RewritePropertySetter() usage for more info. 1390f07576130b93ba7150e04b8bc38aad96a283d074Steve Naroff return ME; 1391c2a689b0bd0cda7bc1522dc0057f01f0897e6d3dSteve Naroff } 13927e20ffe322866f6a2e820e054da9bd0f6e9b0af4Fariborz Jahanian // Get the new text 13933b2c58ce3b1eadc5901efff30cf8bf1885936fe7Chris Lattner // Cannot delete IV->getBase(), since PE points to it. 13943b2c58ce3b1eadc5901efff30cf8bf1885936fe7Chris Lattner // Replace the old base with the cast. This is important when doing 13953b2c58ce3b1eadc5901efff30cf8bf1885936fe7Chris Lattner // embedded rewrites. For example, [newInv->_container addObject:0]. 13961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump IV->setBase(PE); 13973b2c58ce3b1eadc5901efff30cf8bf1885936fe7Chris Lattner return IV; 1398c2a689b0bd0cda7bc1522dc0057f01f0897e6d3dSteve Naroff } 139984472a897a99db80d49eb5ac1ac85d54b1cc6554Steve Naroff } else { // we are outside a method. 14009f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); 14011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14029f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Explicit ivar refs need to have a cast inserted. 14039f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // FIXME: consider sharing some of this code with the code above. 140426337b2f6d4b8dc7458a6e24dca05cb021a21861Fariborz Jahanian if (BaseExpr->getType()->isObjCObjectPointerType()) { 1405c374cd978abdeb289d360426129886f6e354a459Fariborz Jahanian ObjCInterfaceType *iFaceDecl = 1406c374cd978abdeb289d360426129886f6e354a459Fariborz Jahanian dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 14079f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // lookup which class implements the instance variable. 14089f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff ObjCInterfaceDecl *clsDeclared = 0; 14091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 14106ab3524f72a6e64aa04973fa9433b5559abb3525Douglas Gregor clsDeclared); 14119f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 14121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14139f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Synthesize an explicit cast to gain access to the ivar. 14149f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff std::string RecName = clsDeclared->getIdentifier()->getName(); 14159f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff RecName += "_IMPL"; 1416d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer IdentifierInfo *II = &Context->Idents.get(RecName); 1417465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 1418df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek SourceLocation(), II); 14199f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); 14209f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 14219d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, 14229d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, 14239d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall IV->getBase()); 14249f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Don't forget the parens to enforce the proper binding. 14258189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), 14268d36616a093f65f667d22bc1136a4c2be0bae7dfChris Lattner IV->getBase()->getLocEnd(), castExpr); 14272b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian replaced = true; 14289f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Cannot delete IV->getBase(), since PE points to it. 14299f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // Replace the old base with the cast. This is important when doing 14309f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff // embedded rewrites. For example, [newInv->_container addObject:0]. 14311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump IV->setBase(PE); 14329f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff return IV; 14339f525970bec0e29f32cec6141aa3baa245c5ae82Steve Naroff } 1434c2a689b0bd0cda7bc1522dc0057f01f0897e6d3dSteve Naroff } 143584472a897a99db80d49eb5ac1ac85d54b1cc6554Steve Naroff return IV; 14367e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff} 14377e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff 14382b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz JahanianStmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) { 14392b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 14402b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian CI != E; ++CI) { 14412b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (*CI) { 14422b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced); 14432b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (newStmt) 14442b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian *CI = newStmt; 14452b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian } 14462b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian } 14472b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 14482b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian SourceRange OrigStmtRange = S->getSourceRange(); 14492b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(), 14502b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian replaced); 14512b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian return newStmt; 1452376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian } 1453376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) { 1454376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian Stmt *newStmt = SynthMessageExpr(MsgRefExpr); 1455376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian return newStmt; 1456376338a68d467f076c2ae5fa614ec0286ea74d7cFariborz Jahanian } 14572b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian return S; 14582b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian} 14592b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian 1460fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// SynthCountByEnumWithState - To print: 1461fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// ((unsigned int (*) 1462fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 14631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// (void *)objc_msgSend)((id)l_collection, 1464fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// sel_registerName( 14651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// "countByEnumeratingWithState:objects:count:"), 14661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// &enumState, 1467fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// (id *)items, (unsigned int)16) 1468fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1469fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroffvoid RewriteObjC::SynthCountByEnumWithState(std::string &buf) { 1470fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 1471fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff "id *, unsigned int))(void *)objc_msgSend)"; 1472fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "\n\t\t"; 1473fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "((id)l_collection,\n\t\t"; 1474fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; 1475fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "\n\t\t"; 1476fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += "&enumState, " 1477fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff "(id *)items, (unsigned int)16)"; 1478fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 1479b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff 1480fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach 1481fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// statement to exit to its outer synthesized loop. 1482fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1483fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffStmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) { 1484fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1485fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return S; 1486fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // replace break with goto __break_label 1487fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string buf; 14881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1489fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation startLoc = S->getLocStart(); 1490fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf = "goto __break_label_"; 1491fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += utostr(ObjCBcLabelNo.back()); 1492d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, strlen("break"), buf); 14932bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff 1494fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return 0; 1495fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 1496a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian 1497fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach 1498fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// statement to continue with its inner synthesized loop. 1499fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// 1500fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffStmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { 1501fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 1502fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return S; 1503fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // replace continue with goto __continue_label 1504fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string buf; 15051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1506fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation startLoc = S->getLocStart(); 1507fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf = "goto __continue_label_"; 1508fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff buf += utostr(ObjCBcLabelNo.back()); 1509d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, strlen("continue"), buf); 15101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1511e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian return 0; 1512e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian} 1513e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian 1514a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. 151510d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// It rewrites: 151610d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// for ( type elem in collection) { stmts; } 15171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 151810d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// Into: 151910d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// { 15201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// type elem; 152133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// struct __objcFastEnumerationState enumState = { 0 }; 152210d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// id items[16]; 152333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// id l_collection = (id)collection; 15241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 152533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// objects:items count:16]; 152610d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// if (limit) { 152710d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// unsigned long startMutations = *enumState.mutationsPtr; 152810d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// do { 152910d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// unsigned long counter = 0; 153010d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// do { 15311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// if (startMutations != *enumState.mutationsPtr) 153233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// objc_enumerationMutation(l_collection); 153388f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian/// elem = (type)enumState.itemsPtr[counter++]; 153410d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// stmts; 1535e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian/// __continue_label: ; 153610d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } while (counter < limit); 15371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// } while (limit = [l_collection countByEnumeratingWithState:&enumState 153833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// objects:items count:16]); 153933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian/// elem = nil; 1540e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian/// __break_label: ; 154110d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } 154210d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// else 154310d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// elem = nil; 154410d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// } 154510d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian/// 1546b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 1547338d1e2ced8037b71d91fb319631846917d0cedaChris Lattner SourceLocation OrigEnd) { 1548e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); 15491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 1550e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian "ObjCForCollectionStmt Statement stack mismatch"); 15511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(!ObjCBcLabelNo.empty() && 1552e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian "ObjCForCollectionStmt - Label No stack empty"); 15531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 155433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SourceLocation startLoc = S->getLocStart(); 155533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 155633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian const char *elementName; 155788f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian std::string elementTypeAsString; 155833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian std::string buf; 155933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf = "\n{\n\t"; 156033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) { 156133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // type elem; 15627e24e82a70a2c681f4291a3397bcd1e1005f251aChris Lattner NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl()); 15631ed8e2a39456d064a346a6a5c2f6bd53e6d57345Ted Kremenek QualType ElementType = cast<ValueDecl>(D)->getType(); 1564e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff if (ElementType->isObjCQualifiedIdType() || 1565e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff ElementType->isObjCQualifiedInterfaceType()) 1566e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff // Simply use 'id' for all qualified types. 1567e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff elementTypeAsString = "id"; 1568e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff else 1569fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar elementTypeAsString = ElementType.getAsString(Context->PrintingPolicy); 157088f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += elementTypeAsString; 157133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += " "; 15728ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner elementName = D->getNameAsCString(); 157333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 157433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ";\n\t"; 157533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian } 157606767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner else { 157706767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); 15788ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner elementName = DR->getDecl()->getNameAsCString(); 1579e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff ValueDecl *VD = cast<ValueDecl>(DR->getDecl()); 1580e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff if (VD->getType()->isObjCQualifiedIdType() || 1581e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff VD->getType()->isObjCQualifiedInterfaceType()) 1582e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff // Simply use 'id' for all qualified types. 1583e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff elementTypeAsString = "id"; 1584e89b8e7946155db1a3bbb1e22addd5d9d2a904dfSteve Naroff else 1585fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar elementTypeAsString = VD->getType().getAsString(Context->PrintingPolicy); 158688f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian } 15871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 158833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // struct __objcFastEnumerationState enumState = { 0 }; 158933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; 159033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // id items[16]; 159133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "id items[16];\n\t"; 159233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // id l_collection = (id) 159333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "id l_collection = (id)"; 15947571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian // Find start location of 'collection' the hard way! 15957571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian const char *startCollectionBuf = startBuf; 15967571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf += 3; // skip 'for' 15977571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf = strchr(startCollectionBuf, '('); 15987571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf++; // skip '(' 15997571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian // find 'in' and skip it. 16007571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian while (*startCollectionBuf != ' ' || 16017571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' || 16027571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian (*(startCollectionBuf+3) != ' ' && 16037571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) 16047571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf++; 16057571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian startCollectionBuf += 3; 16061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Replace: "for (type element in" with string constructed thus far. 1608d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, startCollectionBuf - startBuf, buf); 160933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Replace ')' in for '(' type elem in collection ')' with ';' 16107571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian SourceLocation rightParenLoc = S->getRParenLoc(); 16117571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian const char *rparenBuf = SM->getCharacterData(rightParenLoc); 16127571228ec9b31de7733ae96352ee4eaa8afcf2b5Fariborz Jahanian SourceLocation lparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf); 161333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf = ";\n\t"; 16141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 161533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 161633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // objects:items count:16]; 161733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // which is synthesized into: 16181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // unsigned int limit = 161933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // ((unsigned int (*) 162033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 16211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // (void *)objc_msgSend)((id)l_collection, 162233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // sel_registerName( 16231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // "countByEnumeratingWithState:objects:count:"), 16241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // (struct __objcFastEnumerationState *)&state, 162533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // (id *)items, (unsigned int)16); 162633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long limit =\n\t\t"; 162733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SynthCountByEnumWithState(buf); 162833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ";\n\t"; 162933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// if (limit) { 163033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// unsigned long startMutations = *enumState.mutationsPtr; 163133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// do { 163233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// unsigned long counter = 0; 163333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// do { 16341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// if (startMutations != *enumState.mutationsPtr) 163533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// objc_enumerationMutation(l_collection); 163688f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian /// elem = (type)enumState.itemsPtr[counter++]; 163733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "if (limit) {\n\t"; 163833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t"; 163933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "do {\n\t\t"; 164033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "unsigned long counter = 0;\n\t\t"; 164133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "do {\n\t\t\t"; 164233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t"; 164333b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "objc_enumerationMutation(l_collection);\n\t\t\t"; 164433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 164588f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += " = ("; 164688f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += elementTypeAsString; 164788f50f31d84185827a8f765dd611134bcaface7bFariborz Jahanian buf += ")enumState.itemsPtr[counter++];"; 164833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Replace ')' in for '(' type elem in collection ')' with all of these. 1649d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lparenLoc, 1, buf); 16501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1651e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian /// __continue_label: ; 165233b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } while (counter < limit); 16531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// } while (limit = [l_collection countByEnumeratingWithState:&enumState 165433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// objects:items count:16]); 165533b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// elem = nil; 1656e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian /// __break_label: ; 165733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } 165833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// else 165933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// elem = nil; 166033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian /// } 16611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump /// 1662e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf = ";\n\t"; 1663e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "__continue_label_"; 1664e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += utostr(ObjCBcLabelNo.back()); 1665e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += ": ;"; 1666e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "\n\t\t"; 166733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "} while (counter < limit);\n\t"; 166833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "} while (limit = "; 166933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian SynthCountByEnumWithState(buf); 167033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += ");\n\t"; 167133b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 167265b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += " = (("; 167365b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += elementTypeAsString; 167465b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += ")0);\n\t"; 1675e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += "__break_label_"; 1676e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += utostr(ObjCBcLabelNo.back()); 1677e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian buf += ": ;\n\t"; 167833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "}\n\t"; 167933b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "else\n\t\t"; 168033b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += elementName; 168165b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += " = (("; 168265b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += elementTypeAsString; 168365b0aa5d3973e07c8c4449ef2b81c389fd48229aFariborz Jahanian buf += ")0);\n\t"; 168433b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian buf += "}\n"; 16851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 168633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian // Insert all these *after* the statement body. 1687d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // FIXME: If this should support Obj-C++, support CXXTryStmt 1688600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff if (isa<CompoundStmt>(S->getBody())) { 1689600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1); 1690d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endBodyLoc, buf); 1691600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff } else { 1692600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff /* Need to treat single statements specially. For example: 1693600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * 1694600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * for (A *a in b) if (stuff()) break; 1695600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * for (A *a in b) xxxyy; 1696600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * 1697600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff * The following code simply scans ahead to the semi to find the actual end. 1698600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff */ 1699600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff const char *stmtBuf = SM->getCharacterData(OrigEnd); 1700600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff const char *semiBuf = strchr(stmtBuf, ';'); 1701600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff assert(semiBuf && "Can't find ';'"); 1702600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(semiBuf-stmtBuf+1); 1703d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endBodyLoc, buf); 1704600e4e8c358fd39e70f3313b7f1bfa0848957597Steve Naroff } 1705e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian Stmts.pop_back(); 1706e8d1c0579404442a87818506bb0e742d0f52d5bfFariborz Jahanian ObjCBcLabelNo.pop_back(); 170733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return 0; 170810d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian} 170910d24f062ee8c83823199191ccdba452c7f9ac24Fariborz Jahanian 17101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// RewriteObjCSynchronizedStmt - 1711a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// This routine rewrites @synchronized(expr) stmt; 1712a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// into: 1713a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// objc_sync_enter(expr); 1714a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// @try stmt @finally { objc_sync_exit(expr); } 1715a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian/// 1716b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 1717a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian // Get the start location and compute the semi location. 1718a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian SourceLocation startLoc = S->getLocStart(); 1719a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian const char *startBuf = SM->getCharacterData(startLoc); 17201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1721a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian assert((*startBuf == '@') && "bogus @synchronized location"); 17221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump std::string buf; 17243498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff buf = "objc_sync_enter((id)"; 17253498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff const char *lparenBuf = startBuf; 17263498cc9793487a5ad51a5a050be85bd550775eccSteve Naroff while (*lparenBuf != '(') lparenBuf++; 1727d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lparenBuf-startBuf+1, buf); 17281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since 17291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // the sync expression is typically a message expression that's already 1730c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff // been rewritten! (which implies the SourceLocation's are invalid). 1731c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff SourceLocation endLoc = S->getSynchBody()->getLocStart(); 1732a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian const char *endBuf = SM->getCharacterData(endLoc); 1733c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff while (*endBuf != ')') endBuf--; 1734c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff SourceLocation rparenLoc = startLoc.getFileLocWithOffset(endBuf-startBuf); 1735a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf = ");\n"; 1736a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian // declare a new scope with two variables, _stack and _rethrow. 1737a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n"; 1738a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "int buf[18/*32-bit i386*/];\n"; 1739a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "char *pointers[4];} _stack;\n"; 1740a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "id volatile _rethrow = 0;\n"; 1741a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "objc_exception_try_enter(&_stack);\n"; 1742a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 1743d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(rparenLoc, 1, buf); 1744a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian startLoc = S->getSynchBody()->getLocEnd(); 1745a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian startBuf = SM->getCharacterData(startLoc); 17461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1747c7089f1be946f3ca6e59596f0e0f92d96136e4c8Steve Naroff assert((*startBuf == '}') && "bogus @synchronized block"); 1748a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian SourceLocation lastCurlyLoc = startLoc; 1749a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf = "}\nelse {\n"; 1750a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1751621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff buf += "}\n"; 1752621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff buf += "{ /* implicit finally clause */\n"; 1753a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 1754b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1755b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string syncBuf; 1756b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += " objc_sync_exit("; 17579d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Expr *syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 17589d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, 17599d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall S->getSynchExpr()); 1760a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string syncExprBufS; 1761a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream syncExprBuf(syncExprBufS); 1762e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner syncExpr->printPretty(syncExprBuf, *Context, 0, 1763e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(LangOpts)); 1764b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += syncExprBuf.str(); 1765b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff syncBuf += ");"; 1766b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1767b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += syncBuf; 1768b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += "\n if (_rethrow) objc_exception_throw(_rethrow);\n"; 1769a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "}\n"; 1770a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian buf += "}"; 17711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1772d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 1773b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1774b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff bool hasReturns = false; 1775b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(S->getSynchBody(), hasReturns); 1776b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (hasReturns) 1777b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteSyncReturnStmts(S->getSynchBody(), syncBuf); 1778b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1779a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian return 0; 1780a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian} 1781a0f55792409289d1d343023fa8292cff6355e538Fariborz Jahanian 1782b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S) 1783b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff{ 17848c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff // Perform a bottom up traversal of all children. 17858c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 17868c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff CI != E; ++CI) 17878c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff if (*CI) 1788b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff WarnAboutReturnGotoStmts(*CI); 17898c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff 1790b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) { 17911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Diags.Report(Context->getFullLoc(S->getLocStart()), 17928c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff TryFinallyContainsReturnDiag); 17938c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff } 17948c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff return; 17958c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff} 17968c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff 1797b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns) 1798b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff{ 1799b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 1800b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 1801b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff CI != E; ++CI) 1802b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) 1803b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(*CI, hasReturns); 1804b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1805b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) 1806b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff hasReturns = true; 1807b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1808b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1809b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1810b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::RewriteTryReturnStmts(Stmt *S) { 1811b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 1812b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 1813b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff CI != E; ++CI) 1814b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) { 1815b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteTryReturnStmts(*CI); 1816b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1817b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) { 1818b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation startLoc = S->getLocStart(); 1819b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 1820b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1821b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 1822b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'"); 1823b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1); 1824b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1825b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string buf; 1826b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf = "{ objc_exception_try_exit(&_stack); return"; 1827b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1828d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 6, buf); 1829d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, "}"); 1830b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1831b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1832b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1833b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1834b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroffvoid RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) { 1835b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Perform a bottom up traversal of all children. 1836b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 1837b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff CI != E; ++CI) 1838b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (*CI) { 1839b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteSyncReturnStmts(*CI, syncExitBuf); 1840b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1841b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (isa<ReturnStmt>(S)) { 1842b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation startLoc = S->getLocStart(); 1843b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 1844b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1845b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff const char *semiBuf = strchr(startBuf, ';'); 1846b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'"); 1847b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1); 1848b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1849b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff std::string buf; 1850b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf = "{ objc_exception_try_exit(&_stack);"; 1851b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += syncExitBuf; 1852b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff buf += " return"; 1853b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1854d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 6, buf); 1855d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(onePastSemiLoc, "}"); 1856b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff } 1857b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff return; 1858b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff} 1859b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 1860b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { 18617573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Get the start location and compute the semi location. 18627573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation startLoc = S->getLocStart(); 18637573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 18641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18657573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @try location"); 18667573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 18677573098b83e780d1c5bea13b384b610d8f155676Steve Naroff std::string buf; 18687573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // declare a new scope with two variables, _stack and _rethrow. 18697573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "/* @try scope begin */ { struct _objc_exception_data {\n"; 18707573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "int buf[18/*32-bit i386*/];\n"; 18717573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "char *pointers[4];} _stack;\n"; 18727573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "id volatile _rethrow = 0;\n"; 18737573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "objc_exception_try_enter(&_stack);\n"; 187421867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; 18757573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 1876d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 4, buf); 18771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 18787573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startLoc = S->getTryBody()->getLocEnd(); 18797573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 18807573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 18817573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '}') && "bogus @try block"); 18821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1883c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff SourceLocation lastCurlyLoc = startLoc; 18848f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (S->getNumCatchStmts()) { 1885c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff startLoc = startLoc.getFileLocWithOffset(1); 1886c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf = " /* @catch begin */ else {\n"; 1887c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " id _caught = objc_exception_extract(&_stack);\n"; 1888c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " objc_exception_try_enter (&_stack);\n"; 1889c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " if (_setjmp(_stack.buf))\n"; 1890c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " _rethrow = objc_exception_extract(&_stack);\n"; 1891c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff buf += " else { /* @catch continue */"; 18921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1893d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, buf); 18948bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff } else { /* no catch list */ 18958bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf = "}\nelse {\n"; 18968bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf += " _rethrow = objc_exception_extract(&_stack);\n"; 18978bd3dc64d28bdb3b263838a12aca25587bce661bSteve Naroff buf += "}"; 1898d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 1899c9ba172447f2e2fe938ae03c3b16b91bda5b4dc3Steve Naroff } 19007573098b83e780d1c5bea13b384b610d8f155676Steve Naroff bool sawIdTypedCatch = false; 19017573098b83e780d1c5bea13b384b610d8f155676Steve Naroff Stmt *lastCatchBody = 0; 19028f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { 19038f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor ObjCAtCatchStmt *Catch = S->getCatchStmt(I); 1904c00d8e18ad3d903acfeb5d05163ce90713066a3fDouglas Gregor VarDecl *catchDecl = Catch->getCatchParamDecl(); 19057573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 19068f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (I == 0) 19077573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "if ("; // we are generating code for the first catch clause 19087573098b83e780d1c5bea13b384b610d8f155676Steve Naroff else 19097573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf = "else if ("; 19108f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor startLoc = Catch->getLocStart(); 19117573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 19121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19137573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @catch location"); 19141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19157573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *lParenLoc = strchr(startBuf, '('); 19167573098b83e780d1c5bea13b384b610d8f155676Steve Naroff 19178f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor if (Catch->hasEllipsis()) { 1918e12e69223ec279e89ac681023d42184b115e0068Steve Naroff // Now rewrite the body... 19198f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor lastCatchBody = Catch->getCatchBody(); 1920e12e69223ec279e89ac681023d42184b115e0068Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocStart(); 1921e12e69223ec279e89ac681023d42184b115e0068Steve Naroff const char *bodyBuf = SM->getCharacterData(bodyLoc); 19228f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor assert(*SM->getCharacterData(Catch->getRParenLoc()) == ')' && 192306767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @catch paren location"); 1924e12e69223ec279e89ac681023d42184b115e0068Steve Naroff assert((*bodyBuf == '{') && "bogus @catch body location"); 19251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1926e12e69223ec279e89ac681023d42184b115e0068Steve Naroff buf += "1) { id _tmp = _caught;"; 1927d7407dc92c7d19cafce429e7e1cf9819d3fc0b92Daniel Dunbar Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf); 19287ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff } else if (catchDecl) { 19297ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff QualType t = catchDecl->getType(); 1930a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (t == Context->getObjCIdType()) { 19317573098b83e780d1c5bea13b384b610d8f155676Steve Naroff buf += "1) { "; 1932d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 19337573098b83e780d1c5bea13b384b610d8f155676Steve Naroff sawIdTypedCatch = true; 1934506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall } else if (const ObjCObjectPointerType *Ptr = 1935506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall t->getAs<ObjCObjectPointerType>()) { 1936506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall // Should be a pointer to a class. 1937506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface(); 1938506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall if (IDecl) { 193921867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; 1940506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall buf += IDecl->getNameAsString(); 194121867b1188ae19b2834c155b21e97c39ed1b9770Steve Naroff buf += "\"), (struct objc_object *)_caught)) { "; 1942d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, lParenLoc-startBuf+1, buf); 19437573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 19447573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 19457573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Now rewrite the body... 19468f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor lastCatchBody = Catch->getCatchBody(); 19478f5e3dd32e443768d9dbbad7191e123e6733750cDouglas Gregor SourceLocation rParenLoc = Catch->getRParenLoc(); 19487573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocStart(); 19497573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *bodyBuf = SM->getCharacterData(bodyLoc); 19507573098b83e780d1c5bea13b384b610d8f155676Steve Naroff const char *rParenBuf = SM->getCharacterData(rParenLoc); 19517573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*rParenBuf == ')') && "bogus @catch paren location"); 19527573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*bodyBuf == '{') && "bogus @catch body location"); 19531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Here we replace ") {" with "= _caught;" (which initializes and 19557573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // declares the @catch parameter). 1956d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;"); 19577ba138abd329e591a8f6d5001f60dd7082f71b3bSteve Naroff } else { 19587573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert(false && "@catch rewrite bug"); 19592bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff } 19607573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 19617573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Complete the catch list... 19627573098b83e780d1c5bea13b384b610d8f155676Steve Naroff if (lastCatchBody) { 19637573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation bodyLoc = lastCatchBody->getLocEnd(); 196406767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner assert(*SM->getCharacterData(bodyLoc) == '}' && 196506767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @catch body location"); 19661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1967378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff // Insert the last (implicit) else clause *before* the right curly brace. 1968378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff bodyLoc = bodyLoc.getFileLocWithOffset(-1); 1969378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf = "} /* last catch end */\n"; 1970378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "else {\n"; 1971378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " _rethrow = _caught;\n"; 1972378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " objc_exception_try_exit(&_stack);\n"; 1973378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "} } /* @catch end */\n"; 1974378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff if (!S->getFinallyStmt()) 1975378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "}\n"; 1976d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(bodyLoc, buf); 19771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19787573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Set lastCurlyLoc 19797573098b83e780d1c5bea13b384b610d8f155676Steve Naroff lastCurlyLoc = lastCatchBody->getLocEnd(); 19807573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 1981a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) { 19827573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startLoc = finalStmt->getLocStart(); 19837573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startBuf = SM->getCharacterData(startLoc); 19847573098b83e780d1c5bea13b384b610d8f155676Steve Naroff assert((*startBuf == '@') && "bogus @finally start"); 19851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1986d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, 8, "/* @finally */"); 19871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19887573098b83e780d1c5bea13b384b610d8f155676Steve Naroff Stmt *body = finalStmt->getFinallyBody(); 19897573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation startLoc = body->getLocStart(); 19907573098b83e780d1c5bea13b384b610d8f155676Steve Naroff SourceLocation endLoc = body->getLocEnd(); 199106767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner assert(*SM->getCharacterData(startLoc) == '{' && 199206767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @finally body location"); 19931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(*SM->getCharacterData(endLoc) == '}' && 199406767518f56cc7ed2a1ae4a37434ad9bdd7890beChris Lattner "bogus @finally body location"); 19951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19967573098b83e780d1c5bea13b384b610d8f155676Steve Naroff startLoc = startLoc.getFileLocWithOffset(1); 1997d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n"); 19987573098b83e780d1c5bea13b384b610d8f155676Steve Naroff endLoc = endLoc.getFileLocWithOffset(-1); 1999d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n"); 20001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20017573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Set lastCurlyLoc 20027573098b83e780d1c5bea13b384b610d8f155676Steve Naroff lastCurlyLoc = body->getLocEnd(); 20031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20048c56515a0c61b73fc2f02cc96dc3e37650d89d45Steve Naroff // Now check for any return/continue/go statements within the @try. 2005b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff WarnAboutReturnGotoStmts(S->getTryBody()); 2006378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff } else { /* no finally clause - make sure we synthesize an implicit one */ 2007378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf = "{ /* implicit finally clause */\n"; 2008378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; 2009378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; 2010378f47afeebe3fde2c17e78ae1cf42d2e3beeacfSteve Naroff buf += "}"; 2011d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(lastCurlyLoc, 1, buf); 2012b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff 2013b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // Now check for any return/continue/go statements within the @try. 2014b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // The implicit finally clause won't called if the @try contains any 2015b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff // jump statements. 2016b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff bool hasReturns = false; 2017b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff HasReturnStmts(S->getTryBody(), hasReturns); 2018b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff if (hasReturns) 2019b85e77af052ea495aa47edcce3b1ec8887e53873Steve Naroff RewriteTryReturnStmts(S->getTryBody()); 20207573098b83e780d1c5bea13b384b610d8f155676Steve Naroff } 20217573098b83e780d1c5bea13b384b610d8f155676Steve Naroff // Now emit the final closing curly brace... 20227573098b83e780d1c5bea13b384b610d8f155676Steve Naroff lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1); 2023d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(lastCurlyLoc, " } /* @try scope end */\n"); 2024909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian return 0; 2025909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian} 2026909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian 2027b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCCatchStmt(ObjCAtCatchStmt *S) { 2028909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian return 0; 2029909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian} 2030909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian 2031b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S) { 2032909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian return 0; 2033909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian} 2034909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian 20351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// This can't be done with ReplaceStmt(S, ThrowExpr), since 20361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// the throw expression is typically a message expression that's already 20372bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff// been rewritten! (which implies the SourceLocation's are invalid). 2038b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { 20392bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff // Get the start location and compute the semi location. 20402bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff SourceLocation startLoc = S->getLocStart(); 20412bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff const char *startBuf = SM->getCharacterData(startLoc); 20421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20432bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff assert((*startBuf == '@') && "bogus @throw location"); 20442bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff 20452bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff std::string buf; 20462bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff /* void objc_exception_throw(id) __attribute__((noreturn)); */ 204720ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff if (S->getThrowExpr()) 204820ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff buf = "objc_exception_throw("; 204920ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff else // add an implicit argument 205020ebf8f15df48f27ce2bf7c1b3ae87565235600fSteve Naroff buf = "objc_exception_throw(_caught"; 20511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20524ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff // handle "@ throw" correctly. 20534ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff const char *wBuf = strchr(startBuf, 'w'); 20544ba0acbe835b12b3755d138f364cd67044d7322fSteve Naroff assert((*wBuf == 'w') && "@throw: can't find 'w'"); 2055d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(startLoc, wBuf-startBuf+1, buf); 20561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20572bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff const char *semiBuf = strchr(startBuf, ';'); 20582bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff assert((*semiBuf == ';') && "@throw: can't find ';'"); 20592bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf); 2060d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(semiLoc, 1, ");"); 20612bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff return 0; 20622bd03923398add1bcb10d40c283cb0eb8ade74daSteve Naroff} 2063909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian 2064b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { 206501c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner // Create a new string expression. 206601c5748c29e75b29cab5fc7d8ad1b173b29c7ecfChris Lattner QualType StrType = Context->getPointerType(Context->CharTy); 206785f9bceab1542aafff012d4d28e998f4ba16e362Anders Carlsson std::string StrEncoding; 20680d504c1da852e58ff802545c823ecff3b6c654b8Daniel Dunbar Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); 20692085fd6cd22ec5c268175251db10d7c60caf7aaaChris Lattner Expr *Replacement = StringLiteral::Create(*Context,StrEncoding.c_str(), 20702085fd6cd22ec5c268175251db10d7c60caf7aaaChris Lattner StrEncoding.length(), false,StrType, 20712085fd6cd22ec5c268175251db10d7c60caf7aaaChris Lattner SourceLocation()); 2072dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, Replacement); 20731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20740750618b0beacdc9b0a9e210a661e4746823ced7Chris Lattner // Replace this subexpr in the parent. 20754c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // delete Exp; leak for now, see RewritePropertySetter() usage for more info. 2076e64b7771dca65d737dfc49b6137bd69fc1ff6bd2Chris Lattner return Replacement; 2077311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner} 2078311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner 2079b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { 20801a9376408941d65c285ddad8a0f1a2ac518df344Steve Naroff if (!SelGetUidFunctionDecl) 20811a9376408941d65c285ddad8a0f1a2ac518df344Steve Naroff SynthSelGetUidFunctionDecl(); 2082b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl"); 2083b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff // Create a call to sel_registerName("selName"). 2084b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff llvm::SmallVector<Expr*, 8> SelExprs; 2085b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff QualType argType = Context->getPointerType(Context->CharTy); 20861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SelExprs.push_back(StringLiteral::Create(*Context, 20876e94ef5696cfb005d3fc7bbac8dcf7690b64f0a5Ted Kremenek Exp->getSelector().getAsString().c_str(), 2088077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner Exp->getSelector().getAsString().size(), 2089726e168dc09fb23f53c7b004f8e919421ee91806Chris Lattner false, argType, SourceLocation())); 2090b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 2091b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff &SelExprs[0], SelExprs.size()); 2092dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, SelExp); 20934c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // delete Exp; leak for now, see RewritePropertySetter() usage for more info. 2094b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff return SelExp; 2095b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff} 2096b42f8415bcfb84c208fd577458ce1bbc2cd800feSteve Naroff 2097b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffCallExpr *RewriteObjC::SynthesizeCallToFunctionDecl( 20981d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc, 20991d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc) { 2100ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Get the type, we will need to reference it in a couple spots. 2101934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff QualType msgSendType = FD->getType(); 21021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2103ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Create a reference to the objc_msgSend() declaration. 21048189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, msgSendType, SourceLocation()); 21051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2106ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff // Now, we cast the reference to a pointer to the objc_msgSend type. 2107f04da137288c48879a86e9e1d4014db8e28dbae1Chris Lattner QualType pToFunc = Context->getPointerType(msgSendType); 210888465d3e996e627bbaa11099b039ddab66d5af2cAnders Carlsson ImplicitCastExpr *ICE = 210988465d3e996e627bbaa11099b039ddab66d5af2cAnders Carlsson new (Context) ImplicitCastExpr(pToFunc, CastExpr::CK_Unknown, 2110f1b48b7014992155286d58bb1676f9f51031d18bAnders Carlsson DRE, CXXBaseSpecifierArray(), 2111906082edf2aea1c6de2926f93a8d7121e49d2a54Sebastian Redl ImplicitCastExpr::RValue); 21121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2113183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *FT = msgSendType->getAs<FunctionType>(); 21141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 21151d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian CallExpr *Exp = 21165291c3cec0dbe8ad1d8e7e67e93af2b1586d5400Douglas Gregor new (Context) CallExpr(*Context, ICE, args, nargs, 21175291c3cec0dbe8ad1d8e7e67e93af2b1586d5400Douglas Gregor FT->getCallResultType(*Context), EndLoc); 21181d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian return Exp; 2119934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff} 2120934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff 2121d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroffstatic bool scanForProtocolRefs(const char *startBuf, const char *endBuf, 2122d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *&startRef, const char *&endRef) { 2123d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff while (startBuf < endBuf) { 2124d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (*startBuf == '<') 2125d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startRef = startBuf; // mark the start. 2126d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (*startBuf == '>') { 212732174826f58d38c20f376fe64ceac4a278133883Steve Naroff if (startRef && *startRef == '<') { 212832174826f58d38c20f376fe64ceac4a278133883Steve Naroff endRef = startBuf; // mark the end. 212932174826f58d38c20f376fe64ceac4a278133883Steve Naroff return true; 213032174826f58d38c20f376fe64ceac4a278133883Steve Naroff } 213132174826f58d38c20f376fe64ceac4a278133883Steve Naroff return false; 2132d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2133d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startBuf++; 2134d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2135d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff return false; 2136d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff} 2137d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff 213861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanianstatic void scanToNextArgument(const char *&argRef) { 213961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian int angle = 0; 214061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian while (*argRef != ')' && (*argRef != ',' || angle > 0)) { 214161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (*argRef == '<') 214261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian angle++; 214361477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else if (*argRef == '>') 214461477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian angle--; 214561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian argRef++; 214661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 214761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian assert(angle == 0 && "scanToNextArgument - bad protocol type syntax"); 214861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian} 2149291e04b29669d6576e19e35555bbc3cadd2f6649Fariborz Jahanian 2150b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffbool RewriteObjC::needToScanForQualifiers(QualType T) { 215132132a08c0aecc316728d81e1d93726707fde14bFariborz Jahanian if (T->isObjCQualifiedIdType()) 215232132a08c0aecc316728d81e1d93726707fde14bFariborz Jahanian return true; 215384aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (const PointerType *PT = T->getAs<PointerType>()) { 215484aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (PT->getPointeeType()->isObjCQualifiedIdType()) 215584aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return true; 215684aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian } 215784aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian if (T->isObjCObjectPointerType()) { 215884aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian T = T->getPointeeType(); 215984aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return T->isObjCQualifiedInterfaceType(); 216084aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian } 216184aa9464a4542b7b63d3b1f9953f9169ce536527Fariborz Jahanian return false; 2162d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff} 2163d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff 21644f95b750534f2111f28434b282bcbd5656002816Steve Naroffvoid RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { 21654f95b750534f2111f28434b282bcbd5656002816Steve Naroff QualType Type = E->getType(); 21664f95b750534f2111f28434b282bcbd5656002816Steve Naroff if (needToScanForQualifiers(Type)) { 2167cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff SourceLocation Loc, EndLoc; 21681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2169cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { 2170cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff Loc = ECE->getLParenLoc(); 2171cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff EndLoc = ECE->getRParenLoc(); 2172cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff } else { 2173cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff Loc = E->getLocStart(); 2174cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff EndLoc = E->getLocEnd(); 2175cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff } 2176cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff // This will defend against trying to rewrite synthesized expressions. 2177cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff if (Loc.isInvalid() || EndLoc.isInvalid()) 2178cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff return; 2179cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff 21804f95b750534f2111f28434b282bcbd5656002816Steve Naroff const char *startBuf = SM->getCharacterData(Loc); 2181cda658e90d7ffe0ece23d741ff82cf764108f66cSteve Naroff const char *endBuf = SM->getCharacterData(EndLoc); 21824f95b750534f2111f28434b282bcbd5656002816Steve Naroff const char *startRef = 0, *endRef = 0; 21834f95b750534f2111f28434b282bcbd5656002816Steve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 21844f95b750534f2111f28434b282bcbd5656002816Steve Naroff // Get the locations of the startRef, endRef. 21854f95b750534f2111f28434b282bcbd5656002816Steve Naroff SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf); 21864f95b750534f2111f28434b282bcbd5656002816Steve Naroff SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1); 21874f95b750534f2111f28434b282bcbd5656002816Steve Naroff // Comment out the protocol references. 2188d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2189d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 21904f95b750534f2111f28434b282bcbd5656002816Steve Naroff } 21914f95b750534f2111f28434b282bcbd5656002816Steve Naroff } 21924f95b750534f2111f28434b282bcbd5656002816Steve Naroff} 21934f95b750534f2111f28434b282bcbd5656002816Steve Naroff 2194b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { 219561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian SourceLocation Loc; 219661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian QualType Type; 219772564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *proto = 0; 219861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) { 219961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Loc = VD->getLocation(); 220061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Type = VD->getType(); 220161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 220261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) { 220361477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Loc = FD->getLocation(); 220461477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // Check for ObjC 'id' and class types that have been adorned with protocol 220561477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // information (id<p>, C<p>*). The protocol references need to be rewritten! 2206183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 220761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian assert(funcType && "missing function type"); 220872564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor proto = dyn_cast<FunctionProtoType>(funcType); 220961477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (!proto) 221061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian return; 221161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian Type = proto->getResultType(); 221261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 22133d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) { 22143d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff Loc = FD->getLocation(); 22153d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff Type = FD->getType(); 22163d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff } 221761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else 2218e66894c3dea9aeab4403e67bf5baabc20da61cb3Fariborz Jahanian return; 22191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 222061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (needToScanForQualifiers(Type)) { 2221d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Since types are unique, we need to scan the buffer. 22221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2223d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *endBuf = SM->getCharacterData(Loc); 2224d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startBuf = endBuf; 22256cafbf2a678c95d4cdc09ecaa782319bbcf56944Steve Naroff while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) 2226d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff startBuf--; // scan backward (from the decl location) for return type. 2227d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startRef = 0, *endRef = 0; 2228d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2229d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Get the locations of the startRef, endRef. 2230d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf); 2231d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1); 2232d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Comment out the protocol references. 2233d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2234d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 2235d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 2236d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 223761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian if (!proto) 223861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian return; // most likely, was a variable 22399165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff // Now check arguments. 224061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian const char *startBuf = SM->getCharacterData(Loc); 224161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian const char *startFuncBuf = startBuf; 22429165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff for (unsigned i = 0; i < proto->getNumArgs(); i++) { 2243d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (needToScanForQualifiers(proto->getArgType(i))) { 2244d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Since types are unique, we need to scan the buffer. 22451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2246d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *endBuf = startBuf; 224761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian // scan forward (from the decl location) for argument types. 224861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian scanToNextArgument(endBuf); 2249d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff const char *startRef = 0, *endRef = 0; 2250d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 2251d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Get the locations of the startRef, endRef. 22521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation LessLoc = 2253291e04b29669d6576e19e35555bbc3cadd2f6649Fariborz Jahanian Loc.getFileLocWithOffset(startRef-startFuncBuf); 22541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation GreaterLoc = 2255291e04b29669d6576e19e35555bbc3cadd2f6649Fariborz Jahanian Loc.getFileLocWithOffset(endRef-startFuncBuf+1); 2256d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff // Comment out the protocol references. 2257d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LessLoc, "/*"); 2258d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(GreaterLoc, "*/"); 2259d5255f55ebe8803ee10b01589a64156e5e9cde5eSteve Naroff } 226061477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf = ++endBuf; 226161477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 226261477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian else { 2263aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff // If the function name is derived from a macro expansion, then the 2264aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff // argument buffer will not follow the name. Need to speak with Chris. 2265aba49d10daaedbc9e8bf6f4c6bfbfa6ea668baa6Steve Naroff while (*startBuf && *startBuf != ')' && *startBuf != ',') 226661477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf++; // scan forward (from the decl location) for argument types. 226761477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian startBuf++; 226861477f7a4ccd3ac785afd9708d77a53869a53a76Fariborz Jahanian } 22699165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff } 22709165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff} 22719165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff 22724c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanianvoid RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) { 22734c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian QualType QT = ND->getType(); 22744c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const Type* TypePtr = QT->getAs<Type>(); 22754c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (!isa<TypeOfExprType>(TypePtr)) 22764c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian return; 22774c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian while (isa<TypeOfExprType>(TypePtr)) { 22784c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 22794c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 22804c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian TypePtr = QT->getAs<Type>(); 22814c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 22824c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian // FIXME. This will not work for multiple declarators; as in: 22834c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian // __typeof__(a) b,c,d; 2284fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string TypeAsString(QT.getAsString(Context->PrintingPolicy)); 22854c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 22864c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *startBuf = SM->getCharacterData(DeclLoc); 22874c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (ND->getInit()) { 22884c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian std::string Name(ND->getNameAsString()); 22894c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian TypeAsString += " " + Name + " = "; 22904c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian Expr *E = ND->getInit(); 22914c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation startLoc; 22924c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 22934c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian startLoc = ECE->getLParenLoc(); 22944c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian else 22954c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian startLoc = E->getLocStart(); 22964c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian startLoc = SM->getInstantiationLoc(startLoc); 22974c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *endBuf = SM->getCharacterData(startLoc); 2298d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 22994c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 23004c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian else { 23014c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian SourceLocation X = ND->getLocEnd(); 23024c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian X = SM->getInstantiationLoc(X); 23034c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian const char *endBuf = SM->getCharacterData(X); 2304d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 23054c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 23064c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian} 23074c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian 2308a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian// SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); 2309b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthSelGetUidFunctionDecl() { 2310a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); 2311a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian llvm::SmallVector<QualType, 16> ArgTys; 23120953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2313a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(), 2314ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor &ArgTys[0], ArgTys.size(), 2315ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor false /*isVariadic*/, 0, 2316264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2317264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2318ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 23191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2320a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis SelGetUidIdent, getFuncType, 0, 232116573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 232216573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 2323a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian} 2324a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian 2325b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { 232609b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff // declared in <objc/objc.h> 232751efe56116a6283ba707cfb8bf8b4e0b13cb41acDouglas Gregor if (FD->getIdentifier() && 232851efe56116a6283ba707cfb8bf8b4e0b13cb41acDouglas Gregor strcmp(FD->getNameAsCString(), "sel_registerName") == 0) { 232909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SelGetUidFunctionDecl = FD; 23309165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff return; 23319165ad378f8d25eb5c378a8e9540089afce421ffSteve Naroff } 2332a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCQualifiedInterfaceTypes(FD); 233309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 233409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2335fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbarvoid RewriteObjC::RewriteBlockPointerType(std::string& Str, QualType Type) { 2336fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string TypeString(Type.getAsString(Context->PrintingPolicy)); 233752b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian const char *argPtr = TypeString.c_str(); 233852b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian if (!strchr(argPtr, '^')) { 233952b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian Str += TypeString; 234052b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian return; 234152b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian } 234252b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian while (*argPtr) { 234352b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian Str += (*argPtr == '^' ? '*' : *argPtr); 234452b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian argPtr++; 234552b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian } 234652b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian} 234752b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian 2348e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian// FIXME. Consolidate this routine with RewriteBlockPointerType. 2349fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbarvoid RewriteObjC::RewriteBlockPointerTypeVariable(std::string& Str, 2350fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar ValueDecl *VD) { 2351e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian QualType Type = VD->getType(); 2352fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string TypeString(Type.getAsString(Context->PrintingPolicy)); 2353e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian const char *argPtr = TypeString.c_str(); 2354e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian int paren = 0; 2355e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian while (*argPtr) { 2356e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian switch (*argPtr) { 2357e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case '(': 2358e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2359e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian paren++; 2360e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2361e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case ')': 2362e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2363e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian paren--; 2364e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2365e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian case '^': 2366e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += '*'; 2367e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian if (paren == 1) 2368e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += VD->getNameAsString(); 2369e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2370e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian default: 2371e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian Str += *argPtr; 2372e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian break; 2373e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 2374e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian argPtr++; 2375e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 2376e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian} 2377e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian 2378e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian 2379abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanianvoid RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { 2380abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 2381abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 2382abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType); 2383abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian if (!proto) 2384abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian return; 2385abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian QualType Type = proto->getResultType(); 2386fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string FdStr = Type.getAsString(Context->PrintingPolicy); 2387abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += " "; 2388abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += FD->getNameAsCString(); 2389abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += "("; 2390abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian unsigned numArgs = proto->getNumArgs(); 2391abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian for (unsigned i = 0; i < numArgs; i++) { 2392abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian QualType ArgType = proto->getArgType(i); 239352b2e1e0775a7a50616b02be4af92295c61e37f5Fariborz Jahanian RewriteBlockPointerType(FdStr, ArgType); 2394abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian if (i+1 < numArgs) 2395abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += ", "; 2396abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian } 2397abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian FdStr += ");\n"; 2398d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, FdStr); 2399abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 2400abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian} 2401abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian 2402c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff// SynthSuperContructorFunctionDecl - id objc_super(id obj, id super); 2403b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthSuperContructorFunctionDecl() { 2404c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff if (SuperContructorFunctionDecl) 2405c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff return; 240646a98a7df016b4a6835a1902c2f8ff2a3a8012baSteve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super"); 2407c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff llvm::SmallVector<QualType, 16> ArgTys; 2408c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff QualType argT = Context->getObjCIdType(); 2409c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff assert(!argT.isNull() && "Can't find 'id' type"); 2410c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff ArgTys.push_back(argT); 2411c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff ArgTys.push_back(argT); 2412c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), 2413c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff &ArgTys[0], ArgTys.size(), 2414ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor false, 0, 2415264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2416264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2417ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2419a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 242016573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 242116573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 2422c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff} 2423c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff 242409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff// SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); 2425b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendFunctionDecl() { 242609b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend"); 242709b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff llvm::SmallVector<QualType, 16> ArgTys; 2428a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 242909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff assert(!argT.isNull() && "Can't find 'id' type"); 243009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff ArgTys.push_back(argT); 2431a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 243209b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff assert(!argT.isNull() && "Can't find 'SEL' type"); 243309b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff ArgTys.push_back(argT); 2434a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), 243509b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff &ArgTys[0], ArgTys.size(), 2436ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor true /*isVariadic*/, 0, 2437264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2438264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2439ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24400ed844b04ea4387caa4e1cf3dc375d269657536bChris Lattner SourceLocation(), 2441a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 244216573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 244316573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 244409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 244509b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2446874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff// SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...); 2447b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendSuperFunctionDecl() { 2448874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); 2449874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff llvm::SmallVector<QualType, 16> ArgTys; 2450465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 24510ed844b04ea4387caa4e1cf3dc375d269657536bChris Lattner SourceLocation(), 2452df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 2453874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 2454874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 2455874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff ArgTys.push_back(argT); 2456a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 2457874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff assert(!argT.isNull() && "Can't find 'SEL' type"); 2458874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff ArgTys.push_back(argT); 2459a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), 2460874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff &ArgTys[0], ArgTys.size(), 2461ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor true /*isVariadic*/, 0, 2462264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2463264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2464ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2466a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 246716573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 246816573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 2469874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff} 2470874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff 247180a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian// SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); 2472b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendStretFunctionDecl() { 247380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret"); 247480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian llvm::SmallVector<QualType, 16> ArgTys; 2475a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 247680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'id' type"); 247780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2478a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 247980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 248080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2481a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), 248280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian &ArgTys[0], ArgTys.size(), 2483ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor true /*isVariadic*/, 0, 2484264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2485264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2486ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 24871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2488a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 248916573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 249016573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 249180a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian} 249280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian 24931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// SynthMsgSendSuperStretFunctionDecl - 249480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian// id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...); 2495b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendSuperStretFunctionDecl() { 24961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump IdentifierInfo *msgSendIdent = 249780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian &Context->Idents.get("objc_msgSendSuper_stret"); 249880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian llvm::SmallVector<QualType, 16> ArgTys; 2499465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 25000ed844b04ea4387caa4e1cf3dc375d269657536bChris Lattner SourceLocation(), 2501df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 250280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian QualType argT = Context->getPointerType(Context->getTagDeclType(RD)); 250380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't build 'struct objc_super *' type"); 250480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2505a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 250680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 250780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian ArgTys.push_back(argT); 2508a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(), 250980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian &ArgTys[0], ArgTys.size(), 2510ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor true /*isVariadic*/, 0, 2511264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2512264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2513ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2515a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 251616573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 251716573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 251880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian} 251980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian 25201284db8d85782c4eb1d41eb02358613c8681f07fSteve Naroff// SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); 2521b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthMsgSendFpretFunctionDecl() { 2522acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret"); 2523acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian llvm::SmallVector<QualType, 16> ArgTys; 2524a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType argT = Context->getObjCIdType(); 2525acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian assert(!argT.isNull() && "Can't find 'id' type"); 2526acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian ArgTys.push_back(argT); 2527a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek argT = Context->getObjCSelType(); 2528acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian assert(!argT.isNull() && "Can't find 'SEL' type"); 2529acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian ArgTys.push_back(argT); 25301284db8d85782c4eb1d41eb02358613c8681f07fSteve Naroff QualType msgSendType = Context->getFunctionType(Context->DoubleTy, 2531acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian &ArgTys[0], ArgTys.size(), 2532ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor true /*isVariadic*/, 0, 2533264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2534264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2535ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2537a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis msgSendIdent, msgSendType, 0, 253816573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 253916573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 2540acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian} 2541acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian 254209b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff// SynthGetClassFunctionDecl - id objc_getClass(const char *name); 2543b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthGetClassFunctionDecl() { 254409b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); 254509b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff llvm::SmallVector<QualType, 16> ArgTys; 25460953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2547a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), 254809b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff &ArgTys[0], ArgTys.size(), 2549ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor false /*isVariadic*/, 0, 2550264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2551264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2552ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2554a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis getClassIdent, getClassType, 0, 255516573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 255616573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 255709b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff} 255809b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff 2559d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian// SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); 2560d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanianvoid RewriteObjC::SynthGetSuperClassFunctionDecl() { 2561d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian IdentifierInfo *getSuperClassIdent = 2562d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian &Context->Idents.get("class_getSuperclass"); 2563d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian llvm::SmallVector<QualType, 16> ArgTys; 2564d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian ArgTys.push_back(Context->getObjCClassType()); 2565d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian QualType getClassType = Context->getFunctionType(Context->getObjCClassType(), 2566d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian &ArgTys[0], ArgTys.size(), 2567d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian false /*isVariadic*/, 0, 2568264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2569264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2570d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 257116573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor SourceLocation(), 257216573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor getSuperClassIdent, 257316573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor getClassType, 0, 257416573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 257516573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, 257616573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor false); 2577d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian} 2578d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian 25799bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name); 2580b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthGetMetaClassFunctionDecl() { 25819bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); 25829bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff llvm::SmallVector<QualType, 16> ArgTys; 25830953e767ff7817f97b3ab20896b229891eeff45bJohn McCall ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 2584a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek QualType getClassType = Context->getFunctionType(Context->getObjCIdType(), 25859bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff &ArgTys[0], ArgTys.size(), 2586ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor false /*isVariadic*/, 0, 2587264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 2588264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 2589ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 25901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2591a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis getClassIdent, getClassType, 0, 259216573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::Extern, 259316573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false); 25949bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff} 25959bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff 2596b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { 2597d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff QualType strType = getConstantStringStructType(); 2598d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 2599d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff std::string S = "__NSConstantStringImpl_"; 26007691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff 26017691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff std::string tmpName = InFileName; 26027691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff unsigned i; 26037691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff for (i=0; i < tmpName.length(); i++) { 26047691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff char c = tmpName.at(i); 26057691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff // replace any non alphanumeric characters with '_'. 26067691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff if (!isalpha(c) && (c < '0' || c > '9')) 26077691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff tmpName[i] = '_'; 26087691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff } 26097691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff S += tmpName; 26107691d9b77b01bf9df6c51e7cb8b43ec150f50b7bSteve Naroff S += "_"; 2611d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff S += utostr(NumObjCStringLiterals++); 2612d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 2613ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "static __NSConstantStringImpl " + S; 2614ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,"; 2615ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += "0x000007c8,"; // utf8_str 2616d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // The pretty printer for StringLiteral handles escape characters properly. 2617a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek std::string prettyBufS; 2618a95d3750441ac8ad03e36af8e6e74039c9a3109dTed Kremenek llvm::raw_string_ostream prettyBuf(prettyBufS); 2619e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner Exp->getString()->printPretty(prettyBuf, *Context, 0, 2620e4f2142d00fa5fdb580c4e2413da91882d955381Chris Lattner PrintingPolicy(LangOpts)); 2621ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += prettyBuf.str(); 2622ba92b2ed976e29ea05f0f5afabaf9488c1096bebSteve Naroff Preamble += ","; 2623fd5b76fe99a123630321b45667a78f1a15be7241Steve Naroff Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; 26241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 26251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 2626d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer &Context->Idents.get(S), strType, 0, 262716573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor VarDecl::Static, VarDecl::None); 26288189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation()); 26298189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, 26301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Context->getPointerType(DRE->getType()), 2631d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff SourceLocation()); 26329698464266660346fa2da1bddc3e6404a9819b25Steve Naroff // cast to NSConstantString * 26339d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), 26349d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, Unop); 2635dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, cast); 26364c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // delete Exp; leak for now, see RewritePropertySetter() usage for more info. 26379698464266660346fa2da1bddc3e6404a9819b25Steve Naroff return cast; 2638beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff} 2639beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff 2640d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanianbool RewriteObjC::isSuperReceiver(Expr *recExpr) { 26419bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff // check if we are sending a message to 'super' 2642d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return false; 2643d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian return isa<ObjCSuperExpr>(recExpr); 2644874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff} 2645874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff 2646874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff// struct objc_super { struct objc_object *receiver; struct objc_class *super; }; 2647b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffQualType RewriteObjC::getSuperStructType() { 2648874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff if (!SuperStructDecl) { 2649465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 26501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2651df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("objc_super")); 2652874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType FieldTypes[2]; 26531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2654874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // struct objc_object *receiver; 26551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[0] = Context->getObjCIdType(); 2656874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // struct objc_class *super; 26571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[1] = Context->getObjCClassType(); 265844b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2659874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // Create fields 266044b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor for (unsigned i = 0; i < 2; ++i) { 26611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, 26621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 0, 2663a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis FieldTypes[i], 0, 2664a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis /*BitWidth=*/0, 26654afa39deaa245592977136d367251ee2c173dd8dDouglas Gregor /*Mutable=*/false)); 266644b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor } 26671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2668838db383b69b9fb55f55c8e9546477df198a4faaDouglas Gregor SuperStructDecl->completeDefinition(); 2669874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } 2670874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff return Context->getTagDeclType(SuperStructDecl); 2671874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff} 2672874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff 2673b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffQualType RewriteObjC::getConstantStringStructType() { 2674d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff if (!ConstantStringDecl) { 2675465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 26761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 2677df042e6c2bf06b2d9ed53c52469599ac1bd93a3fTed Kremenek &Context->Idents.get("__NSConstantStringImpl")); 2678d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff QualType FieldTypes[4]; 26791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2680d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // struct objc_object *receiver; 26811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[0] = Context->getObjCIdType(); 2682d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // int flags; 26831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[1] = Context->IntTy; 2684d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // char *str; 26851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[2] = Context->getPointerType(Context->CharTy); 2686d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // long length; 26871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump FieldTypes[3] = Context->LongTy; 268844b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2689d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff // Create fields 269044b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor for (unsigned i = 0; i < 4; ++i) { 26911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConstantStringDecl->addDecl(FieldDecl::Create(*Context, 26921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConstantStringDecl, 269344b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor SourceLocation(), 0, 2694a1d5662d96465f0fddf8819d245da4d19b892effArgyrios Kyrtzidis FieldTypes[i], 0, 269544b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor /*BitWidth=*/0, 26964afa39deaa245592977136d367251ee2c173dd8dDouglas Gregor /*Mutable=*/true)); 269744b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor } 269844b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor 2699838db383b69b9fb55f55c8e9546477df198a4faaDouglas Gregor ConstantStringDecl->completeDefinition(); 2700d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff } 2701d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff return Context->getTagDeclType(ConstantStringDecl); 2702d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff} 2703d82a9ab4540899e24c96a389c5488381c5551c78Steve Naroff 27041d35b168348a308696d1fce29a18c14143f61d6aFariborz JahanianStmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 27051d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation StartLoc, 27061d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian SourceLocation EndLoc) { 2707a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian if (!SelGetUidFunctionDecl) 2708a70711b296953bfe2fc17351f3908dcc417c404aFariborz Jahanian SynthSelGetUidFunctionDecl(); 270909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff if (!MsgSendFunctionDecl) 271009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SynthMsgSendFunctionDecl(); 2711874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff if (!MsgSendSuperFunctionDecl) 2712874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff SynthMsgSendSuperFunctionDecl(); 271380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (!MsgSendStretFunctionDecl) 271480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SynthMsgSendStretFunctionDecl(); 271580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (!MsgSendSuperStretFunctionDecl) 271680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SynthMsgSendSuperStretFunctionDecl(); 2717acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian if (!MsgSendFpretFunctionDecl) 2718acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian SynthMsgSendFpretFunctionDecl(); 271909b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff if (!GetClassFunctionDecl) 272009b266eb2a014b7af4dc06126c47b7629030ce09Steve Naroff SynthGetClassFunctionDecl(); 2721d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian if (!GetSuperClassFunctionDecl) 2722d314e9e12326c2fd8f140adc4c769d13b483b3f6Fariborz Jahanian SynthGetSuperClassFunctionDecl(); 27239bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff if (!GetMetaClassFunctionDecl) 27249bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff SynthGetMetaClassFunctionDecl(); 27251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2726874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff // default to objc_msgSend(). 272780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 272880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // May need to use objc_msgSend_stret() as well. 272980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian FunctionDecl *MsgSendStretFlavor = 0; 2730621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { 2731621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QualType resultType = mDecl->getResultType(); 2732fb87b89fc9eb103e19fb8e4b925c23f0bd091b99Douglas Gregor if (resultType->isRecordType()) 273380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian MsgSendStretFlavor = MsgSendStretFunctionDecl; 27348b51fd76319d8b71f401cc6ad56e6f4f7be77958Chris Lattner else if (resultType->isRealFloatingType()) 2735acb4977dd3b6a678bfbdb80781bfe3c617be3f24Fariborz Jahanian MsgSendFlavor = MsgSendFpretFunctionDecl; 273680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian } 27371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2738934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Synthesize a call to objc_msgSend(). 2739934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff llvm::SmallVector<Expr*, 8> MsgExprs; 274004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor switch (Exp->getReceiverKind()) { 274104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::SuperClass: { 274204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendFlavor = MsgSendSuperFunctionDecl; 274304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (MsgSendStretFlavor) 274404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 274504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 274604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 274704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 274804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 274904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor llvm::SmallVector<Expr*, 4> InitExprs; 275004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 275104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // set the receiver to self, the first argument to all methods. 275204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 275304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 275404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, 275504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 275604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCIdType(), 275704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation())) 275804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ); // set the 'receiver'. 275904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 276004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 276104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor llvm::SmallVector<Expr*, 8> ClsExprs; 276204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 276304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 276404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClassDecl->getIdentifier()->getNameStart(), 276504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClassDecl->getIdentifier()->getLength(), 276604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor false, argType, SourceLocation())); 276704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, 276804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 276904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 277004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, 277104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor EndLoc); 277204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (Class)objc_getClass("CurrentClass") 277304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 277404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCClassType(), 277504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, Cls); 277604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.clear(); 277704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(ArgExpr); 277804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 277904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], ClsExprs.size(), 278004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 278104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 278204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 278304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // To turn off a warning, type-cast to 'id' 278404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( // set 'super class', using class_getSuperclass(). 278504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, 278604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCIdType(), 278704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, Cls)); 278804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super 278904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType superType = getSuperStructType(); 279004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *SuperRep; 279104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 279204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (LangOpts.Microsoft) { 279304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SynthSuperContructorFunctionDecl(); 279404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Simulate a contructor call... 279504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, 279604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor superType, SourceLocation()); 279704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], 279804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.size(), 279904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor superType, SourceLocation()); 280004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // The code for super is a little tricky to prevent collision with 280104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // the structure definition in the header. The rewriter has it's own 280204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // internal definition (__rw_objc_super) that is uses. This is why 280304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // we need the cast below. For example: 280404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 280504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // 280604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, 280704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 280804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 280904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = NoTypeInfoCStyleCastExpr(Context, 281004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(superType), 281104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, SuperRep); 28129bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff } else { 281304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super) { <exprs from above> } 281404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitListExpr *ILE = 281504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) InitListExpr(*Context, SourceLocation(), 281604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &InitExprs[0], InitExprs.size(), 281704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 281804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor TypeSourceInfo *superTInfo 281904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor = Context->getTrivialTypeSourceInfo(superType); 282004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 282104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor superType, ILE, false); 282204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super * 282304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, 282404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 282504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 28269bcb5fc1fd48c1f40c6a3b5a59130ebc313b4957Steve Naroff } 282704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(SuperRep); 282804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 282904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 283004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 283104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::Class: { 283204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor llvm::SmallVector<Expr*, 8> ClsExprs; 283304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 283404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *Class 2835506b57e8b79d7dc2c367bf2ee7ec95420ad3fc8fJohn McCall = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface(); 283604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor IdentifierInfo *clsName = Class->getIdentifier(); 283704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 283804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor clsName->getNameStart(), 283904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor clsName->getLength(), 284004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor false, argType, 284104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation())); 284204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 284304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 284404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 284504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 284604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(Cls); 284704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 284804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 284904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 285004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::SuperInstance:{ 285104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendFlavor = MsgSendSuperFunctionDecl; 285204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (MsgSendStretFlavor) 285304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 285404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 285504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 285604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor llvm::SmallVector<Expr*, 4> InitExprs; 285704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 285804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 285904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 286004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, 286104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 286204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCIdType(), 286304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation())) 286404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ); // set the 'receiver'. 286504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 286604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 286704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor llvm::SmallVector<Expr*, 8> ClsExprs; 286804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType argType = Context->getPointerType(Context->CharTy); 286904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(StringLiteral::Create(*Context, 287004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClassDecl->getIdentifier()->getNameStart(), 287104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClassDecl->getIdentifier()->getLength(), 287204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor false, argType, SourceLocation())); 287304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 287404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], 287504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.size(), 287604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 287704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (Class)objc_getClass("CurrentClass") 287804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 287904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getObjCClassType(), 288004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, Cls); 288104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.clear(); 288204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor ClsExprs.push_back(ArgExpr); 288304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 288404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &ClsExprs[0], ClsExprs.size(), 288504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor StartLoc, EndLoc); 288604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 288704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 288804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // To turn off a warning, type-cast to 'id' 288904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.push_back( 289004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // set 'super class', using class_getSuperclass(). 289104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 289204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, Cls)); 289304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // struct objc_super 289404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor QualType superType = getSuperStructType(); 289504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *SuperRep; 289604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 289704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor if (LangOpts.Microsoft) { 289804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SynthSuperContructorFunctionDecl(); 289904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Simulate a contructor call... 290004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, 290104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor superType, SourceLocation()); 290204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], 290304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitExprs.size(), 290404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor superType, SourceLocation()); 290504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // The code for super is a little tricky to prevent collision with 290604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // the structure definition in the header. The rewriter has it's own 290704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // internal definition (__rw_objc_super) that is uses. This is why 290804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // we need the cast below. For example: 290904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 291004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // 291104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf, 291204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(SuperRep->getType()), 291304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 291404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = NoTypeInfoCStyleCastExpr(Context, 291504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Context->getPointerType(superType), 291604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, SuperRep); 2917874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } else { 291804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // (struct objc_super) { <exprs from above> } 291904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor InitListExpr *ILE = 292004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor new (Context) InitListExpr(*Context, SourceLocation(), 292104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor &InitExprs[0], InitExprs.size(), 292204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SourceLocation()); 292304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor TypeSourceInfo *superTInfo 292404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor = Context->getTrivialTypeSourceInfo(superType); 292504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 292604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor superType, ILE, false); 2927874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff } 292804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(SuperRep); 292904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 29306568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff } 293104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 293204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor case ObjCMessageExpr::Instance: { 293304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Remove all type-casts because it may contain objc-style types; e.g. 293404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor // Foo<Proto> *. 293504badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor Expr *recExpr = Exp->getInstanceReceiver(); 293604badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) 293704badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor recExpr = CE->getSubExpr(); 293804badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 293904badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor CastExpr::CK_Unknown, recExpr); 294004badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor MsgExprs.push_back(recExpr); 294104badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor break; 294204badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 294304badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor } 294404badcf84c8d504d8491c7c7e29b58f52cb16640Douglas Gregor 2945beaf299a2701c5559a4e5d76b0c40f805afb8e6aSteve Naroff // Create a call to sel_registerName("selName"), it will be the 2nd argument. 2946934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff llvm::SmallVector<Expr*, 8> SelExprs; 2947934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff QualType argType = Context->getPointerType(Context->CharTy); 29481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SelExprs.push_back(StringLiteral::Create(*Context, 29496e94ef5696cfb005d3fc7bbac8dcf7690b64f0a5Ted Kremenek Exp->getSelector().getAsString().c_str(), 2950077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner Exp->getSelector().getAsString().size(), 2951726e168dc09fb23f53c7b004f8e919421ee91806Chris Lattner false, argType, SourceLocation())); 2952934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 29531d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian &SelExprs[0], SelExprs.size(), 29541d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian StartLoc, 29551d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian EndLoc); 2956934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff MsgExprs.push_back(SelExp); 29571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2958934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Now push any user supplied arguments. 2959934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff for (unsigned i = 0; i < Exp->getNumArgs(); i++) { 29606568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff Expr *userExpr = Exp->getArg(i); 29617e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff // Make all implicit casts explicit...ICE comes in handy:-) 29627e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { 29637e3411b23eb3724da5461dc6d6f97d14b3b0a52fSteve Naroff // Reuse the ICE type, it is exactly what the doctor ordered. 296449badde06e066d058d6c7fcf4e628a72999b65a9Douglas Gregor QualType type = ICE->getType()->isObjCQualifiedIdType() 2965a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ? Context->getObjCIdType() 296649badde06e066d058d6c7fcf4e628a72999b65a9Douglas Gregor : ICE->getType(); 29671f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // Make sure we convert "type (^)(...)" to "type (*)(...)". 29684fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(type); 29699d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall userExpr = NoTypeInfoCStyleCastExpr(Context, type, CastExpr::CK_Unknown, 29709d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall userExpr); 2971d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian } 2972d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian // Make id<P...> cast into an 'id' cast. 29736eec8e883de118b431e3ead5b1e604a6ac68ff6bDouglas Gregor else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { 2974a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (CE->getType()->isObjCQualifiedIdType()) { 29756eec8e883de118b431e3ead5b1e604a6ac68ff6bDouglas Gregor while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) 2976d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian userExpr = CE->getSubExpr(); 29779d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 29789d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, userExpr); 2979d58fabf7ed279be18a5e82617f809c9deff9be67Fariborz Jahanian } 29801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 29816568d4dd760f37a945f7c9a249b1500de0777a2dSteve Naroff MsgExprs.push_back(userExpr); 2982621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // We've transferred the ownership to MsgExprs. For now, we *don't* null 2983621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // out the argument in the original expression (since we aren't deleting 2984621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // the ObjCMessageExpr). See RewritePropertySetter() usage for more info. 2985621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff //Exp->setArg(i, 0); 2986934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff } 2987ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Generate the funky cast. 2988ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff CastExpr *cast; 2989ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff llvm::SmallVector<QualType, 8> ArgTypes; 2990ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff QualType returnType; 29911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2992ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Push 'id' and 'SEL', the 2 implicit arguments. 2993c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff if (MsgSendFlavor == MsgSendSuperFunctionDecl) 2994c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff ArgTypes.push_back(Context->getPointerType(getSuperStructType())); 2995c3a438c39ca6061965007c273727f27dfaa4a694Steve Naroff else 2996a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ArgTypes.push_back(Context->getObjCIdType()); 2997a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ArgTypes.push_back(Context->getObjCSelType()); 299889951a86b594513c2a013532ed45d197413b1087Chris Lattner if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { 2999ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Push any user argument types. 300089951a86b594513c2a013532ed45d197413b1087Chris Lattner for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 300189951a86b594513c2a013532ed45d197413b1087Chris Lattner E = OMD->param_end(); PI != E; ++PI) { 300289951a86b594513c2a013532ed45d197413b1087Chris Lattner QualType t = (*PI)->getType()->isObjCQualifiedIdType() 30031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ? Context->getObjCIdType() 300489951a86b594513c2a013532ed45d197413b1087Chris Lattner : (*PI)->getType(); 3005a206b0614a392cfef19aaaa894f9d3c756006421Steve Naroff // Make sure we convert "t (^)(...)" to "t (*)(...)". 30064fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(t); 3007352336bb0a480b044eb03e7359e73d3b173d9cddSteve Naroff ArgTypes.push_back(t); 3008352336bb0a480b044eb03e7359e73d3b173d9cddSteve Naroff } 300989951a86b594513c2a013532ed45d197413b1087Chris Lattner returnType = OMD->getResultType()->isObjCQualifiedIdType() 301089951a86b594513c2a013532ed45d197413b1087Chris Lattner ? Context->getObjCIdType() : OMD->getResultType(); 30114fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(returnType); 3012ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff } else { 3013a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek returnType = Context->getObjCIdType(); 3014ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff } 3015ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Get the type, we will need to reference it in a couple spots. 3016874e232a0d5e179197de860e6dfa3e99cd42ad30Steve Naroff QualType msgSendType = MsgSendFlavor->getType(); 30171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3018ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Create a reference to the objc_msgSend() declaration. 30191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, 302080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SourceLocation()); 3021ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff 30221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 3023ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // If we don't do this cast, we get the following bizarre warning/note: 3024ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // xx.m:13: warning: function called through a non-compatible type 3025ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // xx.m:13: note: if this code is reached, the program will abort 30269d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast = NoTypeInfoCStyleCastExpr(Context, 30279d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Context->getPointerType(Context->VoidTy), 30289d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, DRE); 30291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3030ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Now do the "normal" pointer to function cast. 30311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType castType = Context->getFunctionType(returnType, 3032d0ee6f9f9a5bc5d85e7469f5aabf91f1e71b12f5Fariborz Jahanian &ArgTypes[0], ArgTypes.size(), 30332679e4889fbe1a5582d84363857e020354cedeedSteve Naroff // If we don't have a method decl, force a variadic cast. 3034ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true, 0, 3035264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 3036264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 3037ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff castType = Context->getPointerType(castType); 30389d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown, 30399d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast); 3040ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff 3041ab972d3c4b49fb0b99ae2beee70c1771a05342baSteve Naroff // Don't forget the parens to enforce the proper binding. 30421d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 30431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3044183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *FT = msgSendType->getAs<FunctionType>(); 3045668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 30461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MsgExprs.size(), 30471d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian FT->getResultType(), EndLoc); 304833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian Stmt *ReplacingStmt = CE; 304980a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian if (MsgSendStretFlavor) { 305080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // We have the method which returns a struct/union. Must also generate 305180a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // call to objc_msgSend_stret and hang both varieties on a conditional 305280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // expression which dictate which one to envoke depending on size of 305380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // method's return type. 30541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 305580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Create a reference to the objc_msgSend_stret() declaration. 30561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType, 305780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SourceLocation()); 305880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Need to cast objc_msgSend_stret to "void *" (see above comment). 30599d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast = NoTypeInfoCStyleCastExpr(Context, 30609d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Context->getPointerType(Context->VoidTy), 30619d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, STDRE); 306280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Now do the "normal" pointer to function cast. 30631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump castType = Context->getFunctionType(returnType, 3064d0ee6f9f9a5bc5d85e7469f5aabf91f1e71b12f5Fariborz Jahanian &ArgTypes[0], ArgTypes.size(), 3065ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false, 0, 3066264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola false, false, 0, 0, 3067264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 306880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian castType = Context->getPointerType(castType); 30699d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown, 30709d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall cast); 30711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 307280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Don't forget the parens to enforce the proper binding. 30738189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); 30741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3075183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall FT = msgSendType->getAs<FunctionType>(); 3076668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 30771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump MsgExprs.size(), 3078668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek FT->getResultType(), SourceLocation()); 30791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 308080a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // Build sizeof(returnType) 30811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true, 3082a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall Context->getTrivialTypeSourceInfo(returnType), 30830518999d3adcc289997bd974dce90cc97f5c1c44Sebastian Redl Context->getSizeType(), 30840518999d3adcc289997bd974dce90cc97f5c1c44Sebastian Redl SourceLocation(), SourceLocation()); 308580a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 308680a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. 308780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // For X86 it is more complicated and some kind of target specific routine 308880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // is needed to decide what to do. 30891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump unsigned IntSize = 309098be4943e8dc4f3905629a7102668960873cf863Chris Lattner static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 30911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump IntegerLiteral *limit = new (Context) IntegerLiteral(llvm::APInt(IntSize, 8), 309280a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian Context->IntTy, 309380a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SourceLocation()); 30941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit, 30951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BinaryOperator::LE, 30961eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Context->IntTy, 309780a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian SourceLocation()); 309880a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 30991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ConditionalOperator *CondExpr = 310047e1f7c68bf375cac470fdb2b599ddbb395aeb52Douglas Gregor new (Context) ConditionalOperator(lessThanExpr, 310147e1f7c68bf375cac470fdb2b599ddbb395aeb52Douglas Gregor SourceLocation(), CE, 310247e1f7c68bf375cac470fdb2b599ddbb395aeb52Douglas Gregor SourceLocation(), STCE, returnType); 31038189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), CondExpr); 310480a6a5abbbf0b7c45f535d4e0b0d00f4c3f320eaFariborz Jahanian } 31051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // delete Exp; leak for now, see RewritePropertySetter() usage for more info. 310633b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return ReplacingStmt; 310733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian} 310833b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian 3109b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { 31101d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(), 31111d35b168348a308696d1fce29a18c14143f61d6aFariborz Jahanian Exp->getLocEnd()); 31121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3113934f276cc5b45e19cd12ebb2d04fd7972a23865cSteve Naroff // Now do the actual rewrite. 3114dcbc5b0b0722282a0fdd829359fe0d7e22adb882Chris Lattner ReplaceStmt(Exp, ReplacingStmt); 31151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 31161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // delete Exp; leak for now, see RewritePropertySetter() usage for more info. 311733b9c4e4c6f1b055d94c8b57cd16883125701ac7Fariborz Jahanian return ReplacingStmt; 3118ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff} 3119ebf2b56bce1ea6b1b8133c1f0e2131503d229d2dSteve Naroff 3120621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// typedef struct objc_object Protocol; 3121621edce9cd7d4e06979daf911cc306350619f33bSteve NaroffQualType RewriteObjC::getProtocolType() { 3122621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!ProtocolTypeDecl) { 3123a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall TypeSourceInfo *TInfo 3124a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); 3125621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, 31261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation(), 3127621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff &Context->Idents.get("Protocol"), 3128a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall TInfo); 3129621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3130621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return Context->getTypeDeclType(ProtocolTypeDecl); 3131621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff} 3132621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 313336ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian/// RewriteObjCProtocolExpr - Rewrite a protocol expression into 3134621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// a synthesized/forward data reference (to the protocol's metadata). 3135621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// The forward references (and metadata) are generated in 3136621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// RewriteObjC::HandleTranslationUnit(). 3137b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve NaroffStmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { 3138621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); 3139621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff IdentifierInfo *ID = &Context->Idents.get(Name); 31401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 314116573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor ID, getProtocolType(), 0, 314216573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor VarDecl::Extern, VarDecl::None); 3143621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation()); 3144621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, 3145621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getPointerType(DRE->getType()), 3146621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff SourceLocation()); 31479d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), 31489d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, 31499d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall DerefExpr); 3150621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ReplaceStmt(Exp, castExpr); 3151621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolExprDecls.insert(Exp->getProtocol()); 31521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // delete Exp; leak for now, see RewritePropertySetter() usage for more info. 3153621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return castExpr; 31541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 315536ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian} 315636ee2cb3247a662b6049f9cc097ba5cf9c0bb2b5Fariborz Jahanian 31571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpbool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, 3158baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff const char *endBuf) { 3159baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff while (startBuf < endBuf) { 3160baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (*startBuf == '#') { 3161baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // Skip whitespace. 3162baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf) 3163baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff ; 3164baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (!strncmp(startBuf, "if", strlen("if")) || 3165baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "ifdef", strlen("ifdef")) || 3166baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "ifndef", strlen("ifndef")) || 3167baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "define", strlen("define")) || 3168baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "undef", strlen("undef")) || 3169baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "else", strlen("else")) || 3170baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "elif", strlen("elif")) || 3171baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "endif", strlen("endif")) || 3172baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "pragma", strlen("pragma")) || 3173baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "include", strlen("include")) || 3174baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "import", strlen("import")) || 3175baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff !strncmp(startBuf, "include_next", strlen("include_next"))) 3176baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff return true; 3177baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3178baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff startBuf++; 3179baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3180baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff return false; 3181baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff} 3182baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff 3183a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek/// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to 318426e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian/// an objective-c class with ivars. 3185b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, 318626e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result) { 3187a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); 31881eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert(CDecl->getNameAsCString() && 31892e1cd4264d363ca869bf37ef160902f211d21b8cDouglas Gregor "Name missing in SynthesizeObjCInternalStruct"); 3190212b768a4b39479bc8cce1268a95a1adbd825542Fariborz Jahanian // Do not synthesize more than once. 3191a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (ObjCSynthesizedStructs.count(CDecl)) 3192212b768a4b39479bc8cce1268a95a1adbd825542Fariborz Jahanian return; 3193a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); 3194f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner int NumIvars = CDecl->ivar_size(); 31952c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian SourceLocation LocStart = CDecl->getLocStart(); 31962c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian SourceLocation LocEnd = CDecl->getLocEnd(); 31971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 31982c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian const char *startBuf = SM->getCharacterData(LocStart); 31992c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian const char *endBuf = SM->getCharacterData(LocEnd); 32001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3201aff56d0bffdad7ed75db938d5e61e1ce3d5cd195Fariborz Jahanian // If no ivars and no root or if its root, directly or indirectly, 3202f1de0ca05e2df6f23bd559028693a12d1ebdaaf6Fariborz Jahanian // have no ivars (thus not synthesized) then no need to synthesize this class. 3203f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner if ((CDecl->isForwardDecl() || NumIvars == 0) && 3204f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { 32052c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 3206d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, Result); 320726e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian return; 32082c7038b298c61e531ee4e79b9ff014ffb97b6cccFariborz Jahanian } 32091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME: This has potential of causing problem. If 3211a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek // SynthesizeObjCInternalStruct is ever called recursively. 3212fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result += "\nstruct "; 3213d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 321461ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff if (LangOpts.Microsoft) 321561ed9caca5dd6a9b9ccee7fb51296234e6cc68adSteve Naroff Result += "_IMPL"; 321605b8c782669d07a71d4889bcacfd53a29cd16fcbSteve Naroff 3217fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian if (NumIvars > 0) { 3218fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff const char *cursor = strchr(startBuf, '{'); 32191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert((cursor && endBuf) 3220a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek && "SynthesizeObjCInternalStruct - malformed @interface"); 3221baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // If the buffer contains preprocessor directives, we do more fine-grained 3222baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrites. This is intended to fix code that looks like (which occurs in 3223baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // NSURL.h, for example): 3224baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // 3225baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #ifdef XYZ 3226baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @interface Foo : NSObject 3227baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #else 3228baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @interface FooBar : NSObject 3229baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // #endif 3230baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // { 3231baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // int i; 3232baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // } 3233baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // @end 3234baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // 3235baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // This clause is segregated to avoid breaking the common case. 3236baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff if (BufferContainsPPDirectives(startBuf, cursor)) { 32371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() : 3238baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff CDecl->getClassLoc(); 3239baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff const char *endHeader = SM->getCharacterData(L); 32402c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts); 3241baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff 3242cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl->protocol_begin() != CDecl->protocol_end()) { 3243baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // advance to the end of the referenced protocols. 3244baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff while (endHeader < cursor && *endHeader != '>') endHeader++; 3245baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff endHeader++; 3246baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3247baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrite the original header 3248d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endHeader-startBuf, Result); 3249baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } else { 3250baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff // rewrite the original header *without* disturbing the '{' 3251d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, cursor-startBuf, Result); 3252baf58c3f1fb13eec46fe339287662f180bb566daSteve Naroff } 3253a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 3254fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result = "\n struct "; 3255d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 325639bbd9f5918950436821585afc6244b1fe2c7295Steve Naroff Result += "_IMPL "; 3257d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 3258819173c41e395744480e8f325dc5c02438420604Steve Naroff Result += "_IVARS;\n"; 32591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3260fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // insert the super class structure definition. 3261f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner SourceLocation OnePastCurly = 3262f3dd57e5378bcf5fc9f05832e92479a535d9cd8aChris Lattner LocStart.getFileLocWithOffset(cursor-startBuf+1); 3263d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(OnePastCurly, Result); 3264fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff } 3265fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff cursor++; // past '{' 32661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3267fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // Now comment out any visibility specifiers. 3268fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff while (cursor < endBuf) { 3269fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff if (*cursor == '@') { 3270fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); 3271df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner // Skip whitespace. 3272df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor) 3273df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner /*scan*/; 3274df6a51b0202d10963ed005c2480e3b4a10d16928Chris Lattner 3275fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian // FIXME: presence of @public, etc. inside comment results in 3276fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian // this transformation as well, which is still correct c-code. 3277fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff if (!strncmp(cursor, "public", strlen("public")) || 3278fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff !strncmp(cursor, "private", strlen("private")) || 3279c5e327712499caa2a9f3b6591490de8cb7df0b5bSteve Naroff !strncmp(cursor, "package", strlen("package")) || 32809567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian !strncmp(cursor, "protected", strlen("protected"))) 3281d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, "// "); 3282fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian } 32839567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // FIXME: If there are cases where '<' is used in ivar declaration part 32849567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // of user code, then scan the ivar list and use needToScanForQualifiers 32859567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian // for type checking. 32869567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian else if (*cursor == '<') { 32879567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); 3288d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, "/* "); 32899567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian cursor = strchr(cursor, '>'); 32909567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian cursor++; 32919567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); 3292d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(atLoc, " */"); 3293ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff } else if (*cursor == '^') { // rewrite block specifier. 3294ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff SourceLocation caretLoc = LocStart.getFileLocWithOffset(cursor-startBuf); 3295d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(caretLoc, 1, "*"); 32969567392e164128d853f0005014114d1ffc06fa86Fariborz Jahanian } 3297fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff cursor++; 3298fdc08a06822f7c56cef56e1a813f92565ea8f961Fariborz Jahanian } 3299fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff // Don't forget to add a ';'!! 3300d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(LocEnd.getFileLocWithOffset(1), ";"); 3301fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff } else { // we don't have any instance variables - insert super struct. 33022c78b873f4f3823ae859c15674cb3d76c8554113Chris Lattner endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 3303fea763e8b02eb907c399883117179e898f2abbf8Steve Naroff Result += " {\n struct "; 3304d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 330539bbd9f5918950436821585afc6244b1fe2c7295Steve Naroff Result += "_IMPL "; 3306d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += RCDecl->getNameAsString(); 3307819173c41e395744480e8f325dc5c02438420604Steve Naroff Result += "_IVARS;\n};\n"; 3308d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf, Result); 330926e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian } 331026e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian // Mark this struct as having been generated. 3311a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (!ObjCSynthesizedStructs.insert(CDecl)) 3312fbfe82527dadb09c95609a742744d75a2322850cSteve Naroff assert(false && "struct already synthesize- SynthesizeObjCInternalStruct"); 331326e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian} 331426e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian 3315a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or 33162e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian/// class methods. 3317653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregortemplate<typename MethodIterator> 3318653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregorvoid RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 3319653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor MethodIterator MethodEnd, 33208e991ba2e256e56959a65a049e161aa30b3c0decFariborz Jahanian bool IsInstanceMethod, 33212e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian const char *prefix, 3322158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner const char *ClassName, 3323158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner std::string &Result) { 3324ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner if (MethodBegin == MethodEnd) return; 33251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3326ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner if (!objc_impl_method) { 33272e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian /* struct _objc_method { 3328e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian SEL _cmd; 3329e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian char *method_types; 3330e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian void *_imp; 3331e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 33322e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian */ 3333158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "\nstruct _objc_method {\n"; 3334158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "\tSEL _cmd;\n"; 3335158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "\tchar *method_types;\n"; 3336158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "\tvoid *_imp;\n"; 3337158ecb9767faf87c2a33df3baec1b160dcc0be84Chris Lattner Result += "};\n"; 33381eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3339ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian objc_impl_method = true; 3340ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 33411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3342ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian // Build _objc_method_list for class's methods if needed 33431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3344946a693aea83123f4039012c3bca7bc70800018bSteve Naroff /* struct { 3345946a693aea83123f4039012c3bca7bc70800018bSteve Naroff struct _objc_method_list *next_method; 3346946a693aea83123f4039012c3bca7bc70800018bSteve Naroff int method_count; 3347946a693aea83123f4039012c3bca7bc70800018bSteve Naroff struct _objc_method method_list[]; 3348946a693aea83123f4039012c3bca7bc70800018bSteve Naroff } 3349946a693aea83123f4039012c3bca7bc70800018bSteve Naroff */ 3350653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor unsigned NumMethods = std::distance(MethodBegin, MethodEnd); 3351946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\nstatic struct {\n"; 3352946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tstruct _objc_method_list *next_method;\n"; 3353946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tint method_count;\n"; 3354946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tstruct _objc_method method_list["; 3355653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor Result += utostr(NumMethods); 3356946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "];\n} _OBJC_"; 3357ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += prefix; 3358ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; 3359ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "_METHODS_"; 3360ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += ClassName; 3361dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __"; 3362ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += IsInstanceMethod ? "inst" : "cls"; 3363ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "_meth\")))= "; 3364653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor Result += "{\n\t0, " + utostr(NumMethods) + "\n"; 3365ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner 3366ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "\t,{{(SEL)\""; 3367077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner Result += (*MethodBegin)->getSelector().getAsString().c_str(); 3368ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner std::string MethodTypeString; 3369a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 3370ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "\", \""; 3371ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += MethodTypeString; 3372946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\", (void *)"; 3373ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += MethodInternalNames[*MethodBegin]; 3374ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "}\n"; 3375ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { 3376ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "\t ,{(SEL)\""; 3377077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner Result += (*MethodBegin)->getSelector().getAsString().c_str(); 337833e1d64ab5cd5d27f8530ccd056191fe2c9f3f2eFariborz Jahanian std::string MethodTypeString; 3379a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 338033e1d64ab5cd5d27f8530ccd056191fe2c9f3f2eFariborz Jahanian Result += "\", \""; 338133e1d64ab5cd5d27f8530ccd056191fe2c9f3f2eFariborz Jahanian Result += MethodTypeString; 3382946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\", (void *)"; 3383ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += MethodInternalNames[*MethodBegin]; 3384b7908b5c54aeafc1ff98797e304d61c68b1aed25Fariborz Jahanian Result += "}\n"; 3385e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 3386ab4c4d5e5ececa77aae7e291fafcba3049319cdcChris Lattner Result += "\t }\n};\n"; 33872e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian} 33882e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3389621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. 3390780f329cb011bff0da5763e2e9744eec093d0509Chris Lattnervoid RewriteObjC:: 3391621edce9cd7d4e06979daf911cc306350619f33bSteve NaroffRewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, 3392621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff const char *ClassName, std::string &Result) { 3393e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian static bool objc_protocol_methods = false; 3394621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3395621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output struct protocol_methods holder of method selector and type. 3396621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!objc_protocol_methods && !PDecl->isForwardDecl()) { 3397621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff /* struct protocol_methods { 3398621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff SEL _cmd; 3399621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff char *method_types; 3400621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3401621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff */ 3402621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstruct _protocol_methods {\n"; 3403621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct objc_selector *_cmd;\n"; 3404621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tchar *method_types;\n"; 3405621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "};\n"; 34061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3407621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff objc_protocol_methods = true; 3408621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3409621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Do not synthesize the protocol more than once. 3410621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ObjCSynthesizedProtocols.count(PDecl)) 3411621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return; 34121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 341317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 341417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis unsigned NumMethods = std::distance(PDecl->instmeth_begin(), 341517945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis PDecl->instmeth_end()); 3416621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff /* struct _objc_protocol_method_list { 3417621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff int protocol_method_count; 3418621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct protocol_methods protocols[]; 3419621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3420621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff */ 3421621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstatic struct {\n"; 3422621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tint protocol_method_count;\n"; 3423621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _protocol_methods protocol_methods["; 3424621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += utostr(NumMethods); 3425621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_"; 3426621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3427621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " 3428621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff "{\n\t" + utostr(NumMethods) + "\n"; 34291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3430621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output instance methods declared in this protocol. 34311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCProtocolDecl::instmeth_iterator 34321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 3433621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff I != E; ++I) { 343417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (I == PDecl->instmeth_begin()) 3435621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t ,{{(struct objc_selector *)\""; 3436621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3437621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t ,{(struct objc_selector *)\""; 3438621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += (*I)->getSelector().getAsString().c_str(); 3439621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string MethodTypeString; 3440621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); 3441621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\", \""; 3442621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += MethodTypeString; 3443621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\"}\n"; 34449d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 3445621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t }\n};\n"; 3446621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 34471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3448621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output class methods declared in this protocol. 344917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis unsigned NumMethods = std::distance(PDecl->classmeth_begin(), 345017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis PDecl->classmeth_end()); 3451621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (NumMethods > 0) { 3452621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff /* struct _objc_protocol_method_list { 3453621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff int protocol_method_count; 3454621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct protocol_methods protocols[]; 3455621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 34569d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner */ 3457621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstatic struct {\n"; 3458621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tint protocol_method_count;\n"; 3459621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _protocol_methods protocol_methods["; 3460621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += utostr(NumMethods); 3461621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_"; 3462d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += PDecl->getNameAsString(); 3463621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 3464621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff "{\n\t"; 3465621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += utostr(NumMethods); 3466621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\n"; 34671eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3468621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output instance methods declared in this protocol. 34691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (ObjCProtocolDecl::classmeth_iterator 347017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 3471621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff I != E; ++I) { 347217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (I == PDecl->classmeth_begin()) 3473621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t ,{{(struct objc_selector *)\""; 3474621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3475621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t ,{(struct objc_selector *)\""; 3476621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += (*I)->getSelector().getAsString().c_str(); 3477621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string MethodTypeString; 3478621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); 3479621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\", \""; 3480621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += MethodTypeString; 3481621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\"}\n"; 3482e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 3483621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\t }\n};\n"; 3484621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3485621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3486621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Output: 3487621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff /* struct _objc_protocol { 3488621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Objective-C 1.0 extensions 3489621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct _objc_protocol_extension *isa; 3490621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff char *protocol_name; 3491621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct _objc_protocol **protocol_list; 3492621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct _objc_protocol_method_list *instance_methods; 3493621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff struct _objc_protocol_method_list *class_methods; 34941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 3495621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff */ 3496621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff static bool objc_protocol = false; 3497621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!objc_protocol) { 3498621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstruct _objc_protocol {\n"; 3499621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _objc_protocol_extension *isa;\n"; 3500621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tchar *protocol_name;\n"; 3501621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _objc_protocol **protocol_list;\n"; 3502621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _objc_protocol_method_list *instance_methods;\n"; 3503621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\tstruct _objc_protocol_method_list *class_methods;\n"; 35049d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "};\n"; 35051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3506621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff objc_protocol = true; 3507621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 35081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3509621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_"; 3510621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3511621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= " 3512621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff "{\n\t0, \""; 3513621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3514621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\", 0, "; 351517945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { 3516621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; 3517621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3518621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += ", "; 35199d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 3520621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3521621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "0, "; 352217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (PDecl->classmeth_begin() != PDecl->classmeth_end()) { 3523621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; 3524621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += PDecl->getNameAsString(); 3525621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "\n"; 3526621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 3527621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 3528621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "0\n"; 3529621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "};\n"; 35301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3531621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Mark this protocol as having been generated. 3532621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (!ObjCSynthesizedProtocols.insert(PDecl)) 3533621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff assert(false && "protocol already synthesized"); 3534621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3535621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff} 3536621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 3537621edce9cd7d4e06979daf911cc306350619f33bSteve Naroffvoid RewriteObjC:: 3538621edce9cd7d4e06979daf911cc306350619f33bSteve NaroffRewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, 3539621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff const char *prefix, const char *ClassName, 3540621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string &Result) { 3541621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (Protocols.empty()) return; 35421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3543621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff for (unsigned i = 0; i != Protocols.size(); i++) 3544621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result); 3545621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 35469d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner // Output the top lovel protocol meta-data for the class. 35479d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner /* struct _objc_protocol_list { 35489d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner struct _objc_protocol_list *next; 35499d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner int protocol_count; 35509d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner struct _objc_protocol *class_protocols[]; 35519d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 35529d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner */ 35539d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\nstatic struct {\n"; 35549d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\tstruct _objc_protocol_list *next;\n"; 35559d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\tint protocol_count;\n"; 35569d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\tstruct _objc_protocol *class_protocols["; 35579d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += utostr(Protocols.size()); 35589d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "];\n} _OBJC_"; 35599d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += prefix; 35609d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "_PROTOCOLS_"; 35619d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += ClassName; 35629d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 35639d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner "{\n\t0, "; 35649d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += utostr(Protocols.size()); 35659d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\n"; 35661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 35679d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\t,{&_OBJC_PROTOCOL_"; 3568d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += Protocols[0]->getNameAsString(); 35699d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += " \n"; 35701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 35719d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner for (unsigned i = 1; i != Protocols.size(); i++) { 35729d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\t ,&_OBJC_PROTOCOL_"; 3573d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += Protocols[i]->getNameAsString(); 35749d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\n"; 35759d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner } 35769d0aaa11cd5e657987bbb2d54b63bb0fd18c5117Chris Lattner Result += "\t }\n};\n"; 35772e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian} 35782e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3579621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 35801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category 35812e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian/// implementation. 3582b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, 3583ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian std::string &Result) { 3584a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 35852e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Find category declaration for this implementation. 3586a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCCategoryDecl *CDecl; 35871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (CDecl = ClassDecl->getCategoryList(); CDecl; 35882e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian CDecl = CDecl->getNextClassCategory()) 35892e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian if (CDecl->getIdentifier() == IDecl->getIdentifier()) 35902e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian break; 35911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3592d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string FullCategoryName = ClassDecl->getNameAsString(); 3593eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner FullCategoryName += '_'; 3594d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner FullCategoryName += IDecl->getNameAsString(); 35951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 35962e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Build _objc_method_list for class's instance methods if needed 35971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::SmallVector<ObjCMethodDecl *, 32> 359817945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 3599653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor 3600653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor // If any of our property implementations have associated getters or 3601653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor // setters, produce metadata for them as well. 360217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 360317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis PropEnd = IDecl->propimpl_end(); 3604653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor Prop != PropEnd; ++Prop) { 3605653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 3606653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3607653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (!(*Prop)->getPropertyIvarDecl()) 3608653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3609653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); 3610653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (!PD) 3611653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3612653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 3613653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor InstanceMethods.push_back(Getter); 3614653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (PD->isReadOnly()) 3615653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3616653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 3617653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor InstanceMethods.push_back(Setter); 3618653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor } 3619653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 3620eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner true, "CATEGORY_", FullCategoryName.c_str(), 3621eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner Result); 36221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36232e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Build _objc_method_list for class's class methods if needed 362417945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 3625eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner false, "CATEGORY_", FullCategoryName.c_str(), 3626eb44eeeff28810266259c125896c717d46a0e3b8Chris Lattner Result); 36271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36282e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Protocols referenced in class declaration? 3629bac97d43c9552ac0e084bb81fb7404908f1e9970Fariborz Jahanian // Null CDecl is case of a category implementation with no category interface 3630bac97d43c9552ac0e084bb81fb7404908f1e9970Fariborz Jahanian if (CDecl) 3631621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", 3632621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff FullCategoryName.c_str(), Result); 36332e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian /* struct _objc_category { 36342e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian char *category_name; 36352e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian char *class_name; 36362e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian struct _objc_method_list *instance_methods; 36372e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian struct _objc_method_list *class_methods; 36382e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian struct _objc_protocol_list *protocols; 36392e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Objective-C 1.0 extensions 36402e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian uint32_t size; // sizeof (struct _objc_category) 36411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump struct _objc_property_list *instance_properties; // category's own 36422e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // @property decl. 36431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 36442e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian */ 36451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 36462e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian static bool objc_category = false; 36472e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian if (!objc_category) { 3648ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_category {\n"; 3649ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *category_name;\n"; 3650ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *class_name;\n"; 3651ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_method_list *instance_methods;\n"; 3652ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_method_list *class_methods;\n"; 3653ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_protocol_list *protocols;\n"; 36541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\tunsigned int size;\n"; 3655ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_property_list *instance_properties;\n"; 3656ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 36572e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian objc_category = true; 3658e887c0939572f063b07b6ac2df16140c40fcb667Fariborz Jahanian } 3659ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstatic struct _objc_category _OBJC_CATEGORY_"; 3660ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += FullCategoryName; 3661dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\""; 3662d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += IDecl->getNameAsString(); 3663ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\"\n\t, \""; 3664d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += ClassDecl->getNameAsString(); 3665ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\"\n"; 36661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 366717945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 3668ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, (struct _objc_method_list *)" 3669ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "&_OBJC_CATEGORY_INSTANCE_METHODS_"; 3670ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += FullCategoryName; 3671ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 3672ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 36732e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian else 3674ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, 0\n"; 367517945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 3676ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, (struct _objc_method_list *)" 3677ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "&_OBJC_CATEGORY_CLASS_METHODS_"; 3678ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += FullCategoryName; 3679ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 3680ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 36812e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian else 3682ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, 0\n"; 36831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3684cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) { 36851eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; 3686ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += FullCategoryName; 3687ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 3688ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 36892e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian else 3690ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, 0\n"; 3691ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t, sizeof(struct _objc_category), 0\n};\n"; 36922e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian} 36932e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 369426e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of 369526e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian/// ivar offset. 36967c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanianvoid RewriteObjC::SynthesizeIvarOffsetComputation(ObjCContainerDecl *IDecl, 36971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ObjCIvarDecl *ivar, 369826e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian std::string &Result) { 36998f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff if (ivar->isBitField()) { 37008f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff // FIXME: The hack below doesn't work for bitfields. For now, we simply 37018f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff // place all bitfields at offset 0. 37028f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += "0"; 37038f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff } else { 37048f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += "__OFFSETOFIVAR__(struct "; 3705d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += IDecl->getNameAsString(); 37068f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff if (LangOpts.Microsoft) 37078f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += "_IMPL"; 37088f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += ", "; 3709d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += ivar->getNameAsString(); 37108f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff Result += ")"; 37118f3b2654a9ff6912862f366102f5c46f7757260aSteve Naroff } 371226e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian} 371326e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian 37142e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian//===----------------------------------------------------------------------===// 37152e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian// Meta Data Emission 37162e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian//===----------------------------------------------------------------------===// 37172e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3718b29b427fa977e8e13ea104d22b193b2cd8a4a52fSteve Naroffvoid RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 3719ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian std::string &Result) { 3720a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 37211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3722ebe668fac7553b9932e1936a997e96dc08c9cae4Fariborz Jahanian // Explictly declared @interface's are already synthesized. 372333feeb019a5742b286eededd5446ec0fe87c5a61Steve Naroff if (CDecl->isImplicitInterfaceDecl()) { 37241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME: Implementation of a class with no @interface (legacy) doese not 3725ebe668fac7553b9932e1936a997e96dc08c9cae4Fariborz Jahanian // produce correct synthesis as yet. 3726a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek SynthesizeObjCInternalStruct(CDecl, Result); 3727ebe668fac7553b9932e1936a997e96dc08c9cae4Fariborz Jahanian } 37281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3729be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner // Build _objc_ivar_list metadata for classes ivars if needed 373017945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis unsigned NumIvars = !IDecl->ivar_empty() 37311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ? IDecl->ivar_size() 3732f3a7af901231535191d14cb524d58f22907ac4d2Chris Lattner : (CDecl ? CDecl->ivar_size() : 0); 37332e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian if (NumIvars > 0) { 37342e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian static bool objc_ivar = false; 37352e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian if (!objc_ivar) { 37362e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian /* struct _objc_ivar { 37372e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian char *ivar_name; 37382e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian char *ivar_type; 37392e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian int ivar_offset; 37401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 37412e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian */ 3742ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_ivar {\n"; 3743ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *ivar_name;\n"; 3744ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *ivar_type;\n"; 3745ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tint ivar_offset;\n"; 3746ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 37471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 37482e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian objc_ivar = true; 37492e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian } 37502e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian 3751946a693aea83123f4039012c3bca7bc70800018bSteve Naroff /* struct { 3752946a693aea83123f4039012c3bca7bc70800018bSteve Naroff int ivar_count; 3753946a693aea83123f4039012c3bca7bc70800018bSteve Naroff struct _objc_ivar ivar_list[nIvars]; 37541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 3755946a693aea83123f4039012c3bca7bc70800018bSteve Naroff */ 37561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\nstatic struct {\n"; 3757946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tint ivar_count;\n"; 3758946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "\tstruct _objc_ivar ivar_list["; 3759946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += utostr(NumIvars); 3760946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += "];\n} _OBJC_INSTANCE_VARIABLES_"; 3761d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += IDecl->getNameAsString(); 3762dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " 3763ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "{\n\t"; 3764ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += utostr(NumIvars); 3765ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 37661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3767a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl::ivar_iterator IVI, IVE; 37688f36aba016c2d236a90f9ecf0a66904209202202Douglas Gregor llvm::SmallVector<ObjCIvarDecl *, 8> IVars; 376917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (!IDecl->ivar_empty()) { 377011062e11236b7bc689dad150e8b490fd6b063ec3Fariborz Jahanian for (ObjCInterfaceDecl::ivar_iterator 377117945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); 37728f36aba016c2d236a90f9ecf0a66904209202202Douglas Gregor IV != IVEnd; ++IV) 37738f36aba016c2d236a90f9ecf0a66904209202202Douglas Gregor IVars.push_back(*IV); 377411062e11236b7bc689dad150e8b490fd6b063ec3Fariborz Jahanian IVI = IDecl->ivar_begin(); 377511062e11236b7bc689dad150e8b490fd6b063ec3Fariborz Jahanian IVE = IDecl->ivar_end(); 3776be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner } else { 3777be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner IVI = CDecl->ivar_begin(); 3778be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner IVE = CDecl->ivar_end(); 3779be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner } 3780ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t,{{\""; 3781d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += (*IVI)->getNameAsString(); 3782160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += "\", \""; 3783621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string TmpString, StrEncoding; 3784621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); 3785621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QuoteDoublequotes(TmpString, StrEncoding); 3786160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += StrEncoding; 3787160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += "\", "; 3788be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner SynthesizeIvarOffsetComputation(IDecl, *IVI, Result); 378926e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian Result += "}\n"; 3790be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner for (++IVI; IVI != IVE; ++IVI) { 3791ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t ,{\""; 3792d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += (*IVI)->getNameAsString(); 3793160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += "\", \""; 3794621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff std::string TmpString, StrEncoding; 3795621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); 3796621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff QuoteDoublequotes(TmpString, StrEncoding); 3797160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += StrEncoding; 3798160eb6538eee38b6827a6173c4f7cc0630b29ed5Fariborz Jahanian Result += "\", "; 3799be6df088d69bca0e99c7845a6cd8c1ca85034f31Chris Lattner SynthesizeIvarOffsetComputation(IDecl, (*IVI), Result); 380026e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian Result += "}\n"; 3801ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 38021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3803ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t }\n};\n"; 38042e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian } 38051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38062e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Build _objc_method_list for class's instance methods if needed 38071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump llvm::SmallVector<ObjCMethodDecl *, 32> 380817945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 3809653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor 3810653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor // If any of our property implementations have associated getters or 3811653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor // setters, produce metadata for them as well. 381217945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 381317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis PropEnd = IDecl->propimpl_end(); 3814653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor Prop != PropEnd; ++Prop) { 3815653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 3816653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3817653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (!(*Prop)->getPropertyIvarDecl()) 3818653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3819653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); 3820653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (!PD) 3821653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3822653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 3823653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor InstanceMethods.push_back(Getter); 3824653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (PD->isReadOnly()) 3825653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor continue; 3826653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 3827653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor InstanceMethods.push_back(Setter); 3828653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor } 3829653f1b1bf293a9bd96fd4dd6372e779cc7af1597Douglas Gregor RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), 38308ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner true, "", IDecl->getNameAsCString(), Result); 38311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38322e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Build _objc_method_list for class's class methods if needed 383317945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), 38348ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner false, "", IDecl->getNameAsCString(), Result); 38351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38362e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // Protocols referenced in class declaration? 3837621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), 3838621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff "CLASS", CDecl->getNameAsCString(), Result); 38391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3840deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian // Declaration of class/meta-class metadata 3841deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian /* struct _objc_class { 3842deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian struct _objc_class *isa; // or const char *root_class_name when metadata 38439f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian const char *super_class_name; 38449f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian char *name; 38459f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian long version; 38469f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian long info; 38479f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian long instance_size; 3848deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian struct _objc_ivar_list *ivars; 3849deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian struct _objc_method_list *methods; 38509f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian struct objc_cache *cache; 38519f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian struct objc_protocol_list *protocols; 38529f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian const char *ivar_layout; 38539f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian struct _objc_class_ext *ext; 38541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 38559f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian */ 3856deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian static bool objc_class = false; 3857deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian if (!objc_class) { 3858ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_class {\n"; 3859ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_class *isa;\n"; 3860ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tconst char *super_class_name;\n"; 3861ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tchar *name;\n"; 3862ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong version;\n"; 3863ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong info;\n"; 3864ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong instance_size;\n"; 3865ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_ivar_list *ivars;\n"; 3866ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_method_list *methods;\n"; 3867ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct objc_cache *cache;\n"; 3868ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_protocol_list *protocols;\n"; 3869ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tconst char *ivar_layout;\n"; 3870ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_class_ext *ext;\n"; 3871ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 3872deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian objc_class = true; 38739f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian } 38741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 38759f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian // Meta-class metadata generation. 3876a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *RootClass = 0; 3877a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); 38789f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian while (SuperClass) { 38799f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian RootClass = SuperClass; 38809f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian SuperClass = SuperClass->getSuperClass(); 38819f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian } 38829f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian SuperClass = CDecl->getSuperClass(); 38831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3884ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; 3885d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3886dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " 3887ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "{\n\t(struct _objc_class *)\""; 3888d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString()); 3889ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 3890ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian 3891ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian if (SuperClass) { 3892ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", \""; 3893d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += SuperClass->getNameAsString(); 3894ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\", \""; 3895d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3896ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 3897ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3898ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian else { 3899ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0, \""; 3900d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3901ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 3902ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3903a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. 39049f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian // 'info' field is initialized to CLS_META(2) for metaclass 3905ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0,2, sizeof(struct _objc_class), 0"; 390617945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { 390723f4127411d926fc6a1fe9af7c2bf97e653f16ebSteve Naroff Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; 3908d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += IDecl->getNameAsString(); 39091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\n"; 3910ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 39119f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian else 3912ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0\n"; 3913cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl->protocol_begin() != CDecl->protocol_end()) { 39148eb4a5e70a1bc3d832f90a150fdd84096532c2e2Steve Naroff Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; 3915d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3916ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ",0,0\n"; 3917ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3918454cb012a948ab3dfef5e80ee32b470689c42ba5Fariborz Jahanian else 3919ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t,0,0,0,0\n"; 3920ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 39211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3922deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian // class metadata generation. 3923ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstatic struct _objc_class _OBJC_CLASS_"; 3924d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3925dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= " 3926ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian "{\n\t&_OBJC_METACLASS_"; 3927d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3928ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian if (SuperClass) { 3929ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", \""; 3930d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += SuperClass->getNameAsString(); 3931ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\", \""; 3932d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3933ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 3934ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3935ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian else { 3936ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0, \""; 3937d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3938ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\""; 3939ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3940deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian // 'info' field is initialized to CLS_CLASS(1) for class 39414d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian Result += ", 0,1"; 3942a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek if (!ObjCSynthesizedStructs.count(CDecl)) 39434d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian Result += ",0"; 39444d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian else { 39454d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian // class has size. Must synthesize its size. 3946909f02a69786e94d34d34fc8d4ea3e160bcff775Fariborz Jahanian Result += ",sizeof(struct "; 3947d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3948ba9ac4e5b86842216a0a0eef5886d41e0d7fed0eSteve Naroff if (LangOpts.Microsoft) 3949ba9ac4e5b86842216a0a0eef5886d41e0d7fed0eSteve Naroff Result += "_IMPL"; 39504d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian Result += ")"; 39514d733d3288112667cfa3993424987b9ad9427f8fFariborz Jahanian } 3952ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian if (NumIvars > 0) { 3953c0a123c81b4c88eb713ad2f82e3d7ad0e9ef7c68Steve Naroff Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_"; 3954d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3955ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n\t"; 3956ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3957deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian else 3958ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ",0"; 395917945a0f64fe03ff6ec0c2146005a87636e3ac12Argyrios Kyrtzidis if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { 3960946a693aea83123f4039012c3bca7bc70800018bSteve Naroff Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; 3961d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 39621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += ", 0\n\t"; 3963ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3964deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian else 3965ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ",0,0"; 3966cafeb35117578585dbbfef0bc79d8aa27712bc0eChris Lattner if (CDecl->protocol_begin() != CDecl->protocol_end()) { 39678eb4a5e70a1bc3d832f90a150fdd84096532c2e2Steve Naroff Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; 3968d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CDecl->getNameAsString(); 3969ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ", 0,0\n"; 3970ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 3971deef51838bcf0a1a94832a083fb69ddecd008e8cFariborz Jahanian else 3972ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += ",0,0,0\n"; 3973ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n"; 39749f0a1cb8cf741d8ccd86beb15b50867b0758750fFariborz Jahanian} 3975f4d331dd922f92478ebf30e808c0ca97ce49418bFariborz Jahanian 39767a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian/// RewriteImplementations - This routine rewrites all method implementations 39777a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian/// and emits meta-data. 39787a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian 3979ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroffvoid RewriteObjC::RewriteImplementations() { 3980545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian int ClsDefCount = ClassImplementation.size(); 3981545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian int CatDefCount = CategoryImplementation.size(); 39821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39837a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian // Rewrite implemented methods 39847a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian for (int i = 0; i < ClsDefCount; i++) 39857a3279ddb8b0cdb7444410bc91e2c7419efaedd8Fariborz Jahanian RewriteImplementationDecl(ClassImplementation[i]); 39861eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 398766d6b294af6f114c718039e3279cfd23040cad7bFariborz Jahanian for (int i = 0; i < CatDefCount; i++) 398866d6b294af6f114c718039e3279cfd23040cad7bFariborz Jahanian RewriteImplementationDecl(CategoryImplementation[i]); 3989ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff} 39901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3991ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroffvoid RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { 3992ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff int ClsDefCount = ClassImplementation.size(); 3993ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff int CatDefCount = CategoryImplementation.size(); 39947c63fddad600e710042fa018768807bd04eaa233Fariborz Jahanian 39952e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // For each implemented class, write out all its meta data. 3996f4d331dd922f92478ebf30e808c0ca97ce49418bFariborz Jahanian for (int i = 0; i < ClsDefCount; i++) 3997a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCClassMetaData(ClassImplementation[i], Result); 39981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 39992e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian // For each implemented category, write out all its meta data. 40002e6d935930867d93d84d234ada30d93a0371754dFariborz Jahanian for (int i = 0; i < CatDefCount; i++) 4001a526c5c67e5a0473c340903ee542ce570119665fTed Kremenek RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); 4002621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 4003545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian // Write objc_symtab metadata 4004545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian /* 4005545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian struct _objc_symtab 4006545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian { 4007545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian long sel_ref_cnt; 4008545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian SEL *refs; 4009545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian short cls_def_cnt; 4010545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian short cat_def_cnt; 4011545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian void *defs[cls_def_cnt + cat_def_cnt]; 40121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump }; 4013545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian */ 40141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4015ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_symtab {\n"; 4016ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong sel_ref_cnt;\n"; 4017ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tSEL *refs;\n"; 4018ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tshort cls_def_cnt;\n"; 4019ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tshort cat_def_cnt;\n"; 4020ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n"; 4021ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n\n"; 40221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4023ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "static struct _objc_symtab " 4024dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n"; 40251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\t0, 0, " + utostr(ClsDefCount) 4026ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian + ", " + utostr(CatDefCount) + "\n"; 4027ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian for (int i = 0; i < ClsDefCount; i++) { 4028ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t,&_OBJC_CLASS_"; 4029d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += ClassImplementation[i]->getNameAsString(); 4030ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 4031ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 40321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4033ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian for (int i = 0; i < CatDefCount; i++) { 4034ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\t,&_OBJC_CATEGORY_"; 4035d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CategoryImplementation[i]->getClassInterface()->getNameAsString(); 4036ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "_"; 4037d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner Result += CategoryImplementation[i]->getNameAsString(); 4038ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\n"; 4039ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian } 40401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4041ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n\n"; 40421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4043545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian // Write objc_module metadata 40441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4045545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian /* 4046545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian struct _objc_module { 4047545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian long version; 4048545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian long size; 4049545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian const char *name; 4050545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian struct _objc_symtab *symtab; 4051545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian } 4052545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian */ 40531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4054ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\nstruct _objc_module {\n"; 4055ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong version;\n"; 4056ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tlong size;\n"; 4057ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tconst char *name;\n"; 4058ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "\tstruct _objc_symtab *symtab;\n"; 4059ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n\n"; 4060ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "static struct _objc_module " 4061dbb6543dd11e818df8a3228c6ffcc1976f096b15Steve Naroff "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n"; 40621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Result += "\t" + utostr(OBJC_ABI_VERSION) + 406326e4cd331c389a9b7d51c91981a7a10c8a909bf4Fariborz Jahanian ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n"; 4064ccd87b07a714b6e2735a80e89e425ce7fdf6a8d8Fariborz Jahanian Result += "};\n\n"; 40654f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff 40664f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff if (LangOpts.Microsoft) { 4067621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ProtocolExprDecls.size()) { 4068621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n"; 4069621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "#pragma data_seg(push, \".objc_protocol$B\")\n"; 40701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 4071621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff E = ProtocolExprDecls.end(); I != E; ++I) { 4072621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_"; 4073621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += (*I)->getNameAsString(); 4074621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += " = &_OBJC_PROTOCOL_"; 4075621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += (*I)->getNameAsString(); 4076621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += ";\n"; 4077621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 4078621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Result += "#pragma data_seg(pop)\n\n"; 4079621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff } 40804f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n"; 40811919032c9b6e9969e42093ee2e75a4de6abcb2b0Steve Naroff Result += "#pragma data_seg(push, \".objc_module_info$B\")\n"; 40824f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff Result += "static struct _objc_module *_POINTER_OBJC_MODULES = "; 40834f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff Result += "&_OBJC_MODULES;\n"; 40844f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff Result += "#pragma data_seg(pop)\n\n"; 40854f943c23a47d042c3275e78f2d6015daa650f105Steve Naroff } 4086545b9ae381158761d387d2b5b071f28b1f489ed6Fariborz Jahanian} 4087311ff02fae0392bee6abe7723cdf5a69b2899a47Chris Lattner 4088a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanianvoid RewriteObjC::RewriteByRefString(std::string &ResultStr, 4089a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian const std::string &Name, 4090a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ValueDecl *VD) { 4091a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian assert(BlockByRefDeclNo.count(VD) && 4092a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian "RewriteByRefString: ByRef decl missing"); 4093a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ResultStr += "struct __Block_byref_" + Name + 4094a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian "_" + utostr(BlockByRefDeclNo[VD]) ; 4095a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian} 4096a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian 40976cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanianstatic bool HasLocalVariableExternalStorage(ValueDecl *VD) { 40986cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 40996cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage()); 41006cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return false; 41016cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian} 41026cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 410354055232a5ddb9529726e934301b125cb720a273Steve Naroffstd::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, 410454055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *funcName, 410554055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string Tag) { 410654055232a5ddb9529726e934301b125cb720a273Steve Naroff const FunctionType *AFT = CE->getFunctionType(); 410754055232a5ddb9529726e934301b125cb720a273Steve Naroff QualType RT = AFT->getResultType(); 410854055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string StructRef = "struct " + Tag; 4109fa297fb29b38991c537a0ae90ff595102dcd21a9Daniel Dunbar std::string S = "static " + RT.getAsString(Context->PrintingPolicy) + " __" + 411054055232a5ddb9529726e934301b125cb720a273Steve Naroff funcName + "_" + "block_func_" + utostr(i); 411154055232a5ddb9529726e934301b125cb720a273Steve Naroff 411254055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockDecl *BD = CE->getBlockDecl(); 41131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 411472564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor if (isa<FunctionNoProtoType>(AFT)) { 41151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // No user-supplied arguments. Still need to pass in a pointer to the 4116df8570d1ff98155b74df2a0544068f40b4fd5195Steve Naroff // block (to reference imported block decl refs). 4117df8570d1ff98155b74df2a0544068f40b4fd5195Steve Naroff S += "(" + StructRef + " *__cself)"; 411854055232a5ddb9529726e934301b125cb720a273Steve Naroff } else if (BD->param_empty()) { 411954055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "(" + StructRef + " *__cself)"; 412054055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 412172564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); 412254055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(FT && "SynthesizeBlockFunc: No function proto"); 412354055232a5ddb9529726e934301b125cb720a273Steve Naroff S += '('; 412454055232a5ddb9529726e934301b125cb720a273Steve Naroff // first add the implicit argument. 412554055232a5ddb9529726e934301b125cb720a273Steve Naroff S += StructRef + " *__cself, "; 412654055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string ParamStr; 412754055232a5ddb9529726e934301b125cb720a273Steve Naroff for (BlockDecl::param_iterator AI = BD->param_begin(), 412854055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BD->param_end(); AI != E; ++AI) { 412954055232a5ddb9529726e934301b125cb720a273Steve Naroff if (AI != BD->param_begin()) S += ", "; 4130d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner ParamStr = (*AI)->getNameAsString(); 41311f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType QT = (*AI)->getType(); 41324fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (convertBlockPointerToFunctionPointer(QT)) 41334fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian QT.getAsStringInternal(ParamStr, Context->PrintingPolicy); 41341f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian else 41351f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QT.getAsStringInternal(ParamStr, Context->PrintingPolicy); 413654055232a5ddb9529726e934301b125cb720a273Steve Naroff S += ParamStr; 413754055232a5ddb9529726e934301b125cb720a273Steve Naroff } 413854055232a5ddb9529726e934301b125cb720a273Steve Naroff if (FT->isVariadic()) { 413954055232a5ddb9529726e934301b125cb720a273Steve Naroff if (!BD->param_empty()) S += ", "; 414054055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "..."; 414154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 414254055232a5ddb9529726e934301b125cb720a273Steve Naroff S += ')'; 414354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 414454055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " {\n"; 41451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 414654055232a5ddb9529726e934301b125cb720a273Steve Naroff // Create local declarations to avoid rewriting all closure decl ref exprs. 414754055232a5ddb9529726e934301b125cb720a273Steve Naroff // First, emit a declaration for all "by ref" decls. 4148bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 414954055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByRefDecls.end(); I != E; ++I) { 415054055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " "; 4151d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = (*I)->getNameAsString(); 4152a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian std::string TypeString; 4153a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(TypeString, Name, (*I)); 4154a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian TypeString += " *"; 415552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian Name = TypeString + Name; 4156d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; 41571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 415854055232a5ddb9529726e934301b125cb720a273Steve Naroff // Next, emit a declaration for all "by copy" declarations. 4159bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 416054055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByCopyDecls.end(); I != E; ++I) { 416154055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " "; 416254055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle nested closure invocation. For example: 416354055232a5ddb9529726e934301b125cb720a273Steve Naroff // 416454055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^myImportedClosure)(void); 416554055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedClosure = ^(void) { setGlobalInt(x + y); }; 41661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // 416754055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^anotherClosure)(void); 416854055232a5ddb9529726e934301b125cb720a273Steve Naroff // anotherClosure = ^(void) { 416954055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedClosure(); // import and invoke the closure 417054055232a5ddb9529726e934301b125cb720a273Steve Naroff // }; 417154055232a5ddb9529726e934301b125cb720a273Steve Naroff // 4172e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian if (isTopLevelBlockPointerType((*I)->getType())) { 4173e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian RewriteBlockPointerTypeVariable(S, (*I)); 4174e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian S += " = ("; 4175e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian RewriteBlockPointerType(S, (*I)->getType()); 4176e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian S += ")"; 4177e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n"; 4178e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 4179e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian else { 4180210c248449788d9ef910c8222267029653f83a2fFariborz Jahanian std::string Name = (*I)->getNameAsString(); 41816cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QualType QT = (*I)->getType(); 41826cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(*I)) 41836cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT = Context->getPointerType(QT); 41846cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT.getAsStringInternal(Name, Context->PrintingPolicy); 4185e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian S += Name + " = __cself->" + 4186e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian (*I)->getNameAsString() + "; // bound by copy\n"; 4187e8c28dffce846b1783fd11cc130b4be4f9894301Fariborz Jahanian } 418854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 418954055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string RewrittenStr = RewrittenBlockExprs[CE]; 419054055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *cstr = RewrittenStr.c_str(); 419154055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*cstr++ != '{') ; 419254055232a5ddb9529726e934301b125cb720a273Steve Naroff S += cstr; 419354055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "\n"; 419454055232a5ddb9529726e934301b125cb720a273Steve Naroff return S; 419554055232a5ddb9529726e934301b125cb720a273Steve Naroff} 419654055232a5ddb9529726e934301b125cb720a273Steve Naroff 419754055232a5ddb9529726e934301b125cb720a273Steve Naroffstd::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 419854055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *funcName, 419954055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string Tag) { 420054055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string StructRef = "struct " + Tag; 420154055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string S = "static void __"; 42021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 420354055232a5ddb9529726e934301b125cb720a273Steve Naroff S += funcName; 420454055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "_block_copy_" + utostr(i); 420554055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "(" + StructRef; 420654055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "*dst, " + StructRef; 420754055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "*src) {"; 42081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 420954055232a5ddb9529726e934301b125cb720a273Steve Naroff E = ImportedBlockDecls.end(); I != E; ++I) { 42105bc60d0c324a1b3984cd4a32acb587c8f873ab5fSteve Naroff S += "_Block_object_assign((void*)&dst->"; 4211d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner S += (*I)->getNameAsString(); 421247a242208867fa433d05a78bf346bbb37721a507Steve Naroff S += ", (void*)src->"; 4213d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner S += (*I)->getNameAsString(); 4214bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (BlockByRefDeclsPtrSet.count((*I))) 421573e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 4216d25d1b53f098a4dc52469d9956bdd248ea29b38eFariborz Jahanian else 421773e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 421854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4219d25d1b53f098a4dc52469d9956bdd248ea29b38eFariborz Jahanian S += "}\n"; 4220d25d1b53f098a4dc52469d9956bdd248ea29b38eFariborz Jahanian 422154055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "\nstatic void __"; 422254055232a5ddb9529726e934301b125cb720a273Steve Naroff S += funcName; 422354055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "_block_dispose_" + utostr(i); 422454055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "(" + StructRef; 422554055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "*src) {"; 42261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 422754055232a5ddb9529726e934301b125cb720a273Steve Naroff E = ImportedBlockDecls.end(); I != E; ++I) { 42285bc60d0c324a1b3984cd4a32acb587c8f873ab5fSteve Naroff S += "_Block_object_dispose((void*)src->"; 4229d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner S += (*I)->getNameAsString(); 4230bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (BlockByRefDeclsPtrSet.count((*I))) 423173e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 4232d25d1b53f098a4dc52469d9956bdd248ea29b38eFariborz Jahanian else 423373e437bbe7e9631ad9055b1d50f4ae8564efbdf3Fariborz Jahanian S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 423454055232a5ddb9529726e934301b125cb720a273Steve Naroff } 42351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump S += "}\n"; 423654055232a5ddb9529726e934301b125cb720a273Steve Naroff return S; 423754055232a5ddb9529726e934301b125cb720a273Steve Naroff} 4238ef177820100ab583b08fd3056e2a5a52ee4b1629Argyrios Kyrtzidis 423901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroffstd::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 424001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string Desc) { 4241ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff std::string S = "\nstruct " + Tag; 424254055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string Constructor = " " + Tag; 42431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 424454055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " {\n struct __block_impl impl;\n"; 424501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += " struct " + Desc; 424601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += "* Desc;\n"; 42471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 424801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += "(void *fp, "; // Invoke function pointer. 424901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += "struct " + Desc; // Descriptor pointer. 425001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += " *desc"; 42511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 425254055232a5ddb9529726e934301b125cb720a273Steve Naroff if (BlockDeclRefs.size()) { 425354055232a5ddb9529726e934301b125cb720a273Steve Naroff // Output all "by copy" declarations. 4254bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 425554055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByCopyDecls.end(); I != E; ++I) { 425654055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " "; 4257d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string FieldName = (*I)->getNameAsString(); 425854055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string ArgName = "_" + FieldName; 425954055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle nested closure invocation. For example: 426054055232a5ddb9529726e934301b125cb720a273Steve Naroff // 426154055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^myImportedBlock)(void); 426254055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 42631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // 426454055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^anotherBlock)(void); 426554055232a5ddb9529726e934301b125cb720a273Steve Naroff // anotherBlock = ^(void) { 426654055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedBlock(); // import and invoke the closure 426754055232a5ddb9529726e934301b125cb720a273Steve Naroff // }; 426854055232a5ddb9529726e934301b125cb720a273Steve Naroff // 426901f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType((*I)->getType())) { 427054055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "struct __block_impl *"; 427154055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", void *" + ArgName; 427254055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 42736cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QualType QT = (*I)->getType(); 42746cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(*I)) 42756cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT = Context->getPointerType(QT); 42766cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT.getAsStringInternal(FieldName, Context->PrintingPolicy); 42776cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT.getAsStringInternal(ArgName, Context->PrintingPolicy); 427854055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", " + ArgName; 427954055232a5ddb9529726e934301b125cb720a273Steve Naroff } 428054055232a5ddb9529726e934301b125cb720a273Steve Naroff S += FieldName + ";\n"; 428154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 428254055232a5ddb9529726e934301b125cb720a273Steve Naroff // Output all "by ref" declarations. 4283bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 428454055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByRefDecls.end(); I != E; ++I) { 428554055232a5ddb9529726e934301b125cb720a273Steve Naroff S += " "; 4286d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string FieldName = (*I)->getNameAsString(); 428754055232a5ddb9529726e934301b125cb720a273Steve Naroff std::string ArgName = "_" + FieldName; 428854055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle nested closure invocation. For example: 428954055232a5ddb9529726e934301b125cb720a273Steve Naroff // 429054055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^myImportedBlock)(void); 429154055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 42921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // 429354055232a5ddb9529726e934301b125cb720a273Steve Naroff // void (^anotherBlock)(void); 429454055232a5ddb9529726e934301b125cb720a273Steve Naroff // anotherBlock = ^(void) { 429554055232a5ddb9529726e934301b125cb720a273Steve Naroff // myImportedBlock(); // import and invoke the closure 429654055232a5ddb9529726e934301b125cb720a273Steve Naroff // }; 429754055232a5ddb9529726e934301b125cb720a273Steve Naroff // 429801f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType((*I)->getType())) { 429954055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "struct __block_impl *"; 430054055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", void *" + ArgName; 430154055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 4302a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian std::string TypeString; 4303a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(TypeString, FieldName, (*I)); 430452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian TypeString += " *"; 430552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian FieldName = TypeString + FieldName; 430652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ArgName = TypeString + ArgName; 430754055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", " + ArgName; 430854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 430954055232a5ddb9529726e934301b125cb720a273Steve Naroff S += FieldName + "; // by ref\n"; 431054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 431154055232a5ddb9529726e934301b125cb720a273Steve Naroff // Finish writing the constructor. 431254055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", int flags=0) {\n"; 4313621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (GlobalVarDecl) 4314621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 4315621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 4316621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 431701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 43181eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 431901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += " Desc = desc;\n"; 43201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 432154055232a5ddb9529726e934301b125cb720a273Steve Naroff // Initialize all "by copy" arguments. 4322bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 432354055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByCopyDecls.end(); I != E; ++I) { 4324d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = (*I)->getNameAsString(); 432554055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += " "; 432601f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType((*I)->getType())) 432754055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += Name + " = (struct __block_impl *)_"; 432854055232a5ddb9529726e934301b125cb720a273Steve Naroff else 432954055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += Name + " = _"; 433054055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += Name + ";\n"; 433154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 433254055232a5ddb9529726e934301b125cb720a273Steve Naroff // Initialize all "by ref" arguments. 4333bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 433454055232a5ddb9529726e934301b125cb720a273Steve Naroff E = BlockByRefDecls.end(); I != E; ++I) { 4335d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner std::string Name = (*I)->getNameAsString(); 433654055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += " "; 433701f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType((*I)->getType())) 433854055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += Name + " = (struct __block_impl *)_"; 433954055232a5ddb9529726e934301b125cb720a273Steve Naroff else 434054055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += Name + " = _"; 434152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian Constructor += Name + "->__forwarding;\n"; 434254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 434354055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 434454055232a5ddb9529726e934301b125cb720a273Steve Naroff // Finish writing the constructor. 434554055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += ", int flags=0) {\n"; 4346621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (GlobalVarDecl) 4347621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 4348621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff else 4349621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 435001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 435101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Constructor += " Desc = desc;\n"; 435254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 435354055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += " "; 435454055232a5ddb9529726e934301b125cb720a273Steve Naroff Constructor += "}\n"; 435554055232a5ddb9529726e934301b125cb720a273Steve Naroff S += Constructor; 435654055232a5ddb9529726e934301b125cb720a273Steve Naroff S += "};\n"; 435754055232a5ddb9529726e934301b125cb720a273Steve Naroff return S; 435854055232a5ddb9529726e934301b125cb720a273Steve Naroff} 435939ba4aeca296b1c9f04bde7d9d3cbbf129f1abd3Argyrios Kyrtzidis 436001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroffstd::string RewriteObjC::SynthesizeBlockDescriptor(std::string DescTag, 436101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string ImplTag, int i, 436201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff const char *FunName, 436301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff unsigned hasCopy) { 436401aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string S = "\nstatic struct " + DescTag; 436501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 436601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += " {\n unsigned long reserved;\n"; 436701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += " unsigned long Block_size;\n"; 436801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff if (hasCopy) { 43694fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += " void (*copy)(struct "; 43704fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += ImplTag; S += "*, struct "; 43714fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += ImplTag; S += "*);\n"; 43724fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian 43734fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += " void (*dispose)(struct "; 43744fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian S += ImplTag; S += "*);\n"; 437501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff } 437601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += "} "; 437701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 437801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += DescTag + "_DATA = { 0, sizeof(struct "; 437901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += ImplTag + ")"; 438001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff if (hasCopy) { 438101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += ", __" + std::string(FunName) + "_block_copy_" + utostr(i); 438201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += ", __" + std::string(FunName) + "_block_dispose_" + utostr(i); 438301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff } 438401aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff S += "};\n"; 438501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff return S; 438601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff} 438701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 438854055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, 4389abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian const char *FunName) { 4390abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian // Insert declaration for the function in which block literal is used. 4391bf07012cf92253380ce427924870288a34230d1bFariborz Jahanian if (CurFunctionDeclToDeclareForBlock && !Blocks.empty()) 4392abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 43938611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian bool RewriteSC = (GlobalVarDecl && 43948611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian !Blocks.empty() && 43958611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian GlobalVarDecl->getStorageClass() == VarDecl::Static && 43968611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian GlobalVarDecl->getType().getCVRQualifiers()); 43978611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian if (RewriteSC) { 43988611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian std::string SC(" void __"); 43998611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian SC += GlobalVarDecl->getNameAsString(); 44008611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian SC += "() {}"; 44018611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian InsertText(FunLocStart, SC); 44028611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian } 44038611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian 440454055232a5ddb9529726e934301b125cb720a273Steve Naroff // Insert closures that were part of the function. 440572952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian for (unsigned i = 0, count=0; i < Blocks.size(); i++) { 440672952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian CollectBlockDeclRefInfo(Blocks[i]); 44075e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // Need to copy-in the inner copied-in variables not actually used in this 44085e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // block. 440972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian for (int j = 0; j < InnerDeclRefsCount[i]; j++) { 441072952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockDeclRefExpr *Exp = InnerDeclRefs[count++]; 441172952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian ValueDecl *VD = Exp->getDecl(); 441272952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockDeclRefs.push_back(Exp); 441372952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) { 441472952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByCopyDeclsPtrSet.insert(VD); 441572952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByCopyDecls.push_back(VD); 441672952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 441772952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) { 441872952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByRefDeclsPtrSet.insert(VD); 441972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian BlockByRefDecls.push_back(VD); 442072952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 442172952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 442254055232a5ddb9529726e934301b125cb720a273Steve Naroff 442301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string ImplTag = "__" + std::string(FunName) + "_block_impl_" + utostr(i); 442401aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string DescTag = "__" + std::string(FunName) + "_block_desc_" + utostr(i); 44251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 442601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); 442754055232a5ddb9529726e934301b125cb720a273Steve Naroff 4428d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, CI); 442954055232a5ddb9529726e934301b125cb720a273Steve Naroff 443001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); 44311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4432d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, CF); 443354055232a5ddb9529726e934301b125cb720a273Steve Naroff 443454055232a5ddb9529726e934301b125cb720a273Steve Naroff if (ImportedBlockDecls.size()) { 443501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); 4436d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, HF); 443754055232a5ddb9529726e934301b125cb720a273Steve Naroff } 443801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, 443901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff ImportedBlockDecls.size() > 0); 4440d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, BD); 44411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 444254055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockDeclRefs.clear(); 444354055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockByRefDecls.clear(); 4444bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByRefDeclsPtrSet.clear(); 444554055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockByCopyDecls.clear(); 4446bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByCopyDeclsPtrSet.clear(); 444754055232a5ddb9529726e934301b125cb720a273Steve Naroff ImportedBlockDecls.clear(); 444854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 44498611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian if (RewriteSC) { 445061b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian // Must insert any 'const/volatile/static here. Since it has been 445161b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian // removed as result of rewriting of block literals. 445261b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian std::string SC; 445361b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian if (GlobalVarDecl->getStorageClass() == VarDecl::Static) 445461b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian SC = "static "; 445561b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian if (GlobalVarDecl->getType().isConstQualified()) 445661b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian SC += "const "; 445761b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian if (GlobalVarDecl->getType().isVolatileQualified()) 445861b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian SC += "volatile "; 44598611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian if (GlobalVarDecl->getType().isRestrictQualified()) 44608611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian SC += "restrict "; 44618611eb02e8296bd31ffa31b6eafefd76dd1e299cFariborz Jahanian InsertText(FunLocStart, SC); 446261b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian } 446361b82e3ed67d9c02d8cc0a8c5976e5fb7fad12a8Fariborz Jahanian 446454055232a5ddb9529726e934301b125cb720a273Steve Naroff Blocks.clear(); 44655e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerDeclRefsCount.clear(); 44665e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerDeclRefs.clear(); 446754055232a5ddb9529726e934301b125cb720a273Steve Naroff RewrittenBlockExprs.clear(); 446854055232a5ddb9529726e934301b125cb720a273Steve Naroff} 446954055232a5ddb9529726e934301b125cb720a273Steve Naroff 447054055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { 447154055232a5ddb9529726e934301b125cb720a273Steve Naroff SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 44728ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner const char *FuncName = FD->getNameAsCString(); 44731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 447454055232a5ddb9529726e934301b125cb720a273Steve Naroff SynthesizeBlockLiterals(FunLocStart, FuncName); 447554055232a5ddb9529726e934301b125cb720a273Steve Naroff} 447654055232a5ddb9529726e934301b125cb720a273Steve Naroff 4477e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanianstatic void BuildUniqueMethodName(std::string &Name, 4478e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian ObjCMethodDecl *MD) { 4479e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian ObjCInterfaceDecl *IFace = MD->getClassInterface(); 4480e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian Name = IFace->getNameAsCString(); 4481e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian Name += "__" + MD->getSelector().getAsString(); 4482e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian // Convert colons to underscores. 4483e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian std::string::size_type loc = 0; 4484e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian while ((loc = Name.find(":", loc)) != std::string::npos) 4485e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian Name.replace(loc, 1, "_"); 4486e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian} 4487e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian 448854055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { 4489ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); 4490ced80a848de94ef44b6e7b4ce6f182249b3141a8Steve Naroff //SourceLocation FunLocStart = MD->getLocStart(); 44910e1c99a1a9068020daa7d85fcafb18490ea6a475Fariborz Jahanian SourceLocation FunLocStart = MD->getLocStart(); 4492e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian std::string FuncName; 4493e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian BuildUniqueMethodName(FuncName, MD); 449454055232a5ddb9529726e934301b125cb720a273Steve Naroff SynthesizeBlockLiterals(FunLocStart, FuncName.c_str()); 449554055232a5ddb9529726e934301b125cb720a273Steve Naroff} 449654055232a5ddb9529726e934301b125cb720a273Steve Naroff 449754055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::GetBlockDeclRefExprs(Stmt *S) { 449854055232a5ddb9529726e934301b125cb720a273Steve Naroff for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 449954055232a5ddb9529726e934301b125cb720a273Steve Naroff CI != E; ++CI) 450054055232a5ddb9529726e934301b125cb720a273Steve Naroff if (*CI) { 450154055232a5ddb9529726e934301b125cb720a273Steve Naroff if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) 450254055232a5ddb9529726e934301b125cb720a273Steve Naroff GetBlockDeclRefExprs(CBE->getBody()); 450354055232a5ddb9529726e934301b125cb720a273Steve Naroff else 450454055232a5ddb9529726e934301b125cb720a273Steve Naroff GetBlockDeclRefExprs(*CI); 450554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 450654055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle specific things. 45076cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) { 450854055232a5ddb9529726e934301b125cb720a273Steve Naroff // FIXME: Handle enums. 450954055232a5ddb9529726e934301b125cb720a273Steve Naroff if (!isa<FunctionDecl>(CDRE->getDecl())) 451054055232a5ddb9529726e934301b125cb720a273Steve Naroff BlockDeclRefs.push_back(CDRE); 45116cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 45126cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) 45136cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(DRE->getDecl())) { 45146cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian BlockDeclRefExpr *BDRE = 45156cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian new (Context)BlockDeclRefExpr(DRE->getDecl(), DRE->getType(), 45166cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian DRE->getLocation(), false); 45176cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian BlockDeclRefs.push_back(BDRE); 45186cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 45196cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 452054055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 452154055232a5ddb9529726e934301b125cb720a273Steve Naroff} 452254055232a5ddb9529726e934301b125cb720a273Steve Naroff 45235e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanianvoid RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, 45245e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs, 452572952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) { 45265e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 45275e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian CI != E; ++CI) 45285e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian if (*CI) { 452972952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) { 453072952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl())); 45315e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian GetInnerBlockDeclRefExprs(CBE->getBody(), 45325e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerBlockDeclRefs, 453372952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerContexts); 453472952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian } 45355e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian else 45365e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian GetInnerBlockDeclRefExprs(*CI, 45375e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerBlockDeclRefs, 453872952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerContexts); 45395e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 45405e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian } 45415e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // Handle specific things. 45426cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) { 45435e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian if (!isa<FunctionDecl>(CDRE->getDecl()) && 454472952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian !InnerContexts.count(CDRE->getDecl()->getDeclContext())) 45455e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerBlockDeclRefs.push_back(CDRE); 45466cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 45476cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 45486cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) 45496cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (Var->isFunctionOrMethodVarDecl()) 45506cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ImportedLocalExternalDecls.insert(Var); 45516cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 455272952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian 45535e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian return; 45545e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian} 45555e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 45561f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian/// convertFunctionTypeOfBlocks - This routine converts a function type 45571f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian/// whose result type may be a block pointer or whose argument type(s) 45581f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian/// might be block pointers to an equivalent funtion type replacing 45591f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian/// all block pointers to function pointers. 45601f90622e9d24064164df1608ea125d0ed451ac68Fariborz JahanianQualType RewriteObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { 45611f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 45621f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // FTP will be null for closures that don't take arguments. 45631f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // Generate a funky cast. 45641f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian llvm::SmallVector<QualType, 8> ArgTypes; 45651f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType Res = FT->getResultType(); 45664fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian bool HasBlockType = convertBlockPointerToFunctionPointer(Res); 45671f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian 45681f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian if (FTP) { 45691f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 45701f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian E = FTP->arg_type_end(); I && (I != E); ++I) { 45711f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType t = *I; 45721f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // Make sure we convert "t (^)(...)" to "t (*)(...)". 45734fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian if (convertBlockPointerToFunctionPointer(t)) 45741f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian HasBlockType = true; 45751f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian ArgTypes.push_back(t); 45761f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian } 45771f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian } 45781f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType FuncType; 45791f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // FIXME. Does this work if block takes no argument but has a return type 45801f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian // which is of block type? 45811f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian if (HasBlockType) 45821f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian FuncType = Context->getFunctionType(Res, 45831f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian &ArgTypes[0], ArgTypes.size(), false/*no variadic*/, 0, 45841f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian false, false, 0, 0, FunctionType::ExtInfo()); 45851f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian else FuncType = QualType(FT, 0); 45861f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian return FuncType; 45871f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian} 45881f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian 45898a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz JahanianStmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 459054055232a5ddb9529726e934301b125cb720a273Steve Naroff // Navigate to relevant type information. 459154055232a5ddb9529726e934301b125cb720a273Steve Naroff const BlockPointerType *CPT = 0; 45921eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 45938a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { 45946217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek CPT = DRE->getType()->getAs<BlockPointerType>(); 45958a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian } else if (const BlockDeclRefExpr *CDRE = 45968a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian dyn_cast<BlockDeclRefExpr>(BlockExp)) { 45976217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek CPT = CDRE->getType()->getAs<BlockPointerType>(); 45988a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { 45996217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek CPT = MExpr->getType()->getAs<BlockPointerType>(); 46008a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian } 46018a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) { 46028a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian return SynthesizeBlockCall(Exp, PRE->getSubExpr()); 46038a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian } 46048a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 46058a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian CPT = IEXPR->getType()->getAs<BlockPointerType>(); 46068a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian else if (const ConditionalOperator *CEXPR = 46078a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian dyn_cast<ConditionalOperator>(BlockExp)) { 46088a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Expr *LHSExp = CEXPR->getLHS(); 46098a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp); 46108a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Expr *RHSExp = CEXPR->getRHS(); 46118a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); 46128a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Expr *CONDExp = CEXPR->getCond(); 46138a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian ConditionalOperator *CondExpr = 46148a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian new (Context) ConditionalOperator(CONDExp, 46158a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian SourceLocation(), cast<Expr>(LHSStmt), 46168a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian SourceLocation(), cast<Expr>(RHSStmt), 46178a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Exp->getType()); 46188a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian return CondExpr; 4619e24b22bb58e38253da0bda26da51da7663ca743bFariborz Jahanian } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { 4620e24b22bb58e38253da0bda26da51da7663ca743bFariborz Jahanian CPT = IRE->getType()->getAs<BlockPointerType>(); 462154055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 462254055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(1 && "RewriteBlockClass: Bad type"); 462354055232a5ddb9529726e934301b125cb720a273Steve Naroff } 462454055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(CPT && "RewriteBlockClass: Bad type"); 4625183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); 462654055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(FT && "RewriteBlockClass: Bad type"); 462772564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 462854055232a5ddb9529726e934301b125cb720a273Steve Naroff // FTP will be null for closures that don't take arguments. 46291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4630465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 4631aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff SourceLocation(), 4632aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff &Context->Idents.get("__block_impl")); 4633aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); 463454055232a5ddb9529726e934301b125cb720a273Steve Naroff 4635aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Generate a funky cast. 4636aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff llvm::SmallVector<QualType, 8> ArgTypes; 46371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4638aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Push the block argument type. 4639aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff ArgTypes.push_back(PtrBlock); 464054055232a5ddb9529726e934301b125cb720a273Steve Naroff if (FTP) { 46411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 4642aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff E = FTP->arg_type_end(); I && (I != E); ++I) { 4643aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff QualType t = *I; 4644aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Make sure we convert "t (^)(...)" to "t (*)(...)". 46454fc8453dd02d015b1161d83a5740632617aedd12Fariborz Jahanian (void)convertBlockPointerToFunctionPointer(t); 4646aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff ArgTypes.push_back(t); 4647aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff } 4648aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff } 4649aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Now do the pointer to function cast. 46501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump QualType PtrToFuncCastType = Context->getFunctionType(Exp->getType(), 4651ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor &ArgTypes[0], ArgTypes.size(), false/*no variadic*/, 0, 4652ce056bcaa1c97b89a4b2de2112c62d060863be2bDouglas Gregor false, false, 0, 0, 4653264ba48dc98f3f843935a485d5b086f7e0fdc4f1Rafael Espindola FunctionType::ExtInfo()); 46541eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4655aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); 46561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 46579d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock, 46589d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, 46599d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall const_cast<Expr*>(BlockExp)); 4660aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Don't forget the parens to enforce the proper binding. 46618189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 46628189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek BlkCast); 4663aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff //PE->dump(); 46641eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 466544b4321feab46299d3f5cfd404680884752a0fcfDouglas Gregor FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 46661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump &Context->Idents.get("FuncPtr"), Context->VoidPtrTy, 0, 46674afa39deaa245592977136d367251ee2c173dd8dDouglas Gregor /*BitWidth=*/0, /*Mutable=*/true); 46688189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 46698189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek FD->getType()); 46701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 46719d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, 46729d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, ME); 46738189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); 46741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 4675aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff llvm::SmallVector<Expr*, 8> BlkExprs; 4676aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Add the implicit argument. 4677aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff BlkExprs.push_back(BlkCast); 4678aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff // Add the user arguments. 46791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (CallExpr::arg_iterator I = Exp->arg_begin(), 468054055232a5ddb9529726e934301b125cb720a273Steve Naroff E = Exp->arg_end(); I != E; ++I) { 4681aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff BlkExprs.push_back(*I); 468254055232a5ddb9529726e934301b125cb720a273Steve Naroff } 4683668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0], 4684668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek BlkExprs.size(), 46858189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Exp->getType(), SourceLocation()); 4686aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff return CE; 468754055232a5ddb9529726e934301b125cb720a273Steve Naroff} 468854055232a5ddb9529726e934301b125cb720a273Steve Naroff 468954055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::RewriteBlockCall(CallExpr *Exp) { 46908a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *BlockCall = SynthesizeBlockCall(Exp, Exp->getCallee()); 4691aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff ReplaceStmt(Exp, BlockCall); 469254055232a5ddb9529726e934301b125cb720a273Steve Naroff} 469354055232a5ddb9529726e934301b125cb720a273Steve Naroff 4694621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// We need to return the rewritten expression to handle cases where the 4695621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// BlockDeclRefExpr is embedded in another expression being rewritten. 4696621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// For example: 4697621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// 4698621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// int main() { 4699621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// __block Foo *f; 4700621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// __block int i; 47011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump// 4702621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// void (^myblock)() = ^() { 4703621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten). 4704621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// i = 77; 4705621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff// }; 4706621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff//} 4707f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz JahanianStmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) { 4708bbf37e232b10793b9ec91f4ea01ec168123d5026Fariborz Jahanian // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 4709f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian // for each DeclRefExp where BYREFVAR is name of the variable. 4710f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ValueDecl *VD; 4711f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian bool isArrow = true; 4712f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp)) 4713f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian VD = BDRE->getDecl(); 4714f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian else { 4715f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian VD = cast<DeclRefExpr>(DeclRefExp)->getDecl(); 4716f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian isArrow = false; 4717f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian } 4718f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian 4719ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 4720ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian &Context->Idents.get("__forwarding"), 4721ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian Context->VoidPtrTy, 0, 4722ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian /*BitWidth=*/0, /*Mutable=*/true); 4723f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow, 4724f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian FD, SourceLocation(), 4725ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian FD->getType()); 4726f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian 4727f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian const char *Name = VD->getNameAsCString(); 4728ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian FD = FieldDecl::Create(*Context, 0, SourceLocation(), 4729ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian &Context->Idents.get(Name), 4730ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian Context->VoidPtrTy, 0, 4731ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian /*BitWidth=*/0, /*Mutable=*/true); 4732ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(), 4733f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian DeclRefExp->getType()); 4734ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian 4735ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian 4736ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian 4737df8570d1ff98155b74df2a0544068f40b4fd5195Steve Naroff // Need parens to enforce precedence. 4738ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 4739ec878f2726e00e6dc0c432f462dab099e3f4a717Fariborz Jahanian ME); 4740f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ReplaceStmt(DeclRefExp, PE); 4741621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return PE; 474254055232a5ddb9529726e934301b125cb720a273Steve Naroff} 474354055232a5ddb9529726e934301b125cb720a273Steve Naroff 47446cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian// Rewrites the imported local variable V with external storage 47456cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian// (static, extern, etc.) as *V 47466cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian// 47476cb6eb4c792b504ad652d9230640656852e18ee9Fariborz JahanianStmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { 47486cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ValueDecl *VD = DRE->getDecl(); 47496cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 47506cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (!ImportedLocalExternalDecls.count(Var)) 47516cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return DRE; 47526cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian Expr *Exp = new (Context) UnaryOperator(DRE, UnaryOperator::Deref, 47536cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian DRE->getType(), DRE->getLocation()); 47546cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian // Need parens to enforce precedence. 47556cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 47566cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian Exp); 47576cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ReplaceStmt(DRE, PE); 47586cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return PE; 47596cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian} 47606cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 4761b2f9e516327310d95840d442416084508f80c183Steve Naroffvoid RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { 4762b2f9e516327310d95840d442416084508f80c183Steve Naroff SourceLocation LocStart = CE->getLParenLoc(); 4763b2f9e516327310d95840d442416084508f80c183Steve Naroff SourceLocation LocEnd = CE->getRParenLoc(); 4764fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 4765fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Need to avoid trying to rewrite synthesized casts. 4766fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (LocStart.isInvalid()) 4767fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 47688f6ce5796fb74daf0c4cd39fbda9f7ceb1c7a7b6Steve Naroff // Need to avoid trying to rewrite casts contained in macros. 47698f6ce5796fb74daf0c4cd39fbda9f7ceb1c7a7b6Steve Naroff if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) 47708f6ce5796fb74daf0c4cd39fbda9f7ceb1c7a7b6Steve Naroff return; 47711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 477254055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *startBuf = SM->getCharacterData(LocStart); 477354055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *endBuf = SM->getCharacterData(LocEnd); 47741d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian QualType QT = CE->getType(); 47751d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian const Type* TypePtr = QT->getAs<Type>(); 47761d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian if (isa<TypeOfExprType>(TypePtr)) { 47771d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 47781d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 47791d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian std::string TypeAsString = "("; 4780afad76f6134e635c3cb240ec725d3b7989e7a625Fariborz Jahanian RewriteBlockPointerType(TypeAsString, QT); 47811d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian TypeAsString += ")"; 4782d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); 47831d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian return; 47841d4fca2e42da8506cc1042a1ea93815a8e9ae0f0Fariborz Jahanian } 478554055232a5ddb9529726e934301b125cb720a273Steve Naroff // advance the location to startArgList. 478654055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *argPtr = startBuf; 47871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 478854055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*argPtr++ && (argPtr < endBuf)) { 478954055232a5ddb9529726e934301b125cb720a273Steve Naroff switch (*argPtr) { 4790b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case '^': 4791b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Replace the '^' with '*'. 4792b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf); 4793d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(LocStart, 1, "*"); 4794b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 479554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 479654055232a5ddb9529726e934301b125cb720a273Steve Naroff } 479754055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 479854055232a5ddb9529726e934301b125cb720a273Steve Naroff} 479954055232a5ddb9529726e934301b125cb720a273Steve Naroff 480054055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { 480154055232a5ddb9529726e934301b125cb720a273Steve Naroff SourceLocation DeclLoc = FD->getLocation(); 480254055232a5ddb9529726e934301b125cb720a273Steve Naroff unsigned parenCount = 0; 48031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 480454055232a5ddb9529726e934301b125cb720a273Steve Naroff // We have 1 or more arguments that have closure pointers. 480554055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *startBuf = SM->getCharacterData(DeclLoc); 480654055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *startArgList = strchr(startBuf, '('); 48071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 480854055232a5ddb9529726e934301b125cb720a273Steve Naroff assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); 48091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 481054055232a5ddb9529726e934301b125cb720a273Steve Naroff parenCount++; 481154055232a5ddb9529726e934301b125cb720a273Steve Naroff // advance the location to startArgList. 481254055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclLoc = DeclLoc.getFileLocWithOffset(startArgList-startBuf); 481354055232a5ddb9529726e934301b125cb720a273Steve Naroff assert((DeclLoc.isValid()) && "Invalid DeclLoc"); 48141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 481554055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *argPtr = startArgList; 48161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 481754055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*argPtr++ && parenCount) { 481854055232a5ddb9529726e934301b125cb720a273Steve Naroff switch (*argPtr) { 4819b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case '^': 4820b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump // Replace the '^' with '*'. 4821b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList); 4822d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, 1, "*"); 4823b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 4824b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case '(': 4825b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump parenCount++; 4826b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 4827b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case ')': 4828b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump parenCount--; 4829b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump break; 483054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 483154055232a5ddb9529726e934301b125cb720a273Steve Naroff } 483254055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 483354055232a5ddb9529726e934301b125cb720a273Steve Naroff} 483454055232a5ddb9529726e934301b125cb720a273Steve Naroff 483554055232a5ddb9529726e934301b125cb720a273Steve Naroffbool RewriteObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { 483672564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor const FunctionProtoType *FTP; 48376217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek const PointerType *PT = QT->getAs<PointerType>(); 483854055232a5ddb9529726e934301b125cb720a273Steve Naroff if (PT) { 4839183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 484054055232a5ddb9529726e934301b125cb720a273Steve Naroff } else { 48416217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 484254055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 4843183700f494ec9b6701b6efe82bcb25f4c79ba561John McCall FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 484454055232a5ddb9529726e934301b125cb720a273Steve Naroff } 484554055232a5ddb9529726e934301b125cb720a273Steve Naroff if (FTP) { 48461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 484754055232a5ddb9529726e934301b125cb720a273Steve Naroff E = FTP->arg_type_end(); I != E; ++I) 484801f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(*I)) 484954055232a5ddb9529726e934301b125cb720a273Steve Naroff return true; 485054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 485154055232a5ddb9529726e934301b125cb720a273Steve Naroff return false; 485254055232a5ddb9529726e934301b125cb720a273Steve Naroff} 485354055232a5ddb9529726e934301b125cb720a273Steve Naroff 48548189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenekvoid RewriteObjC::GetExtentOfArgList(const char *Name, const char *&LParen, 48558189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek const char *&RParen) { 485654055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *argPtr = strchr(Name, '('); 485754055232a5ddb9529726e934301b125cb720a273Steve Naroff assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); 48581eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 485954055232a5ddb9529726e934301b125cb720a273Steve Naroff LParen = argPtr; // output the start. 486054055232a5ddb9529726e934301b125cb720a273Steve Naroff argPtr++; // skip past the left paren. 486154055232a5ddb9529726e934301b125cb720a273Steve Naroff unsigned parenCount = 1; 48621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 486354055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*argPtr && parenCount) { 486454055232a5ddb9529726e934301b125cb720a273Steve Naroff switch (*argPtr) { 4865b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case '(': parenCount++; break; 4866b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump case ')': parenCount--; break; 4867b7166334d897e1e4e6a5b428fe2d0ec752ef187fMike Stump default: break; 486854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 486954055232a5ddb9529726e934301b125cb720a273Steve Naroff if (parenCount) argPtr++; 487054055232a5ddb9529726e934301b125cb720a273Steve Naroff } 487154055232a5ddb9529726e934301b125cb720a273Steve Naroff assert((*argPtr == ')') && "Rewriter fuzzy parser confused"); 487254055232a5ddb9529726e934301b125cb720a273Steve Naroff RParen = argPtr; // output the end 487354055232a5ddb9529726e934301b125cb720a273Steve Naroff} 487454055232a5ddb9529726e934301b125cb720a273Steve Naroff 487554055232a5ddb9529726e934301b125cb720a273Steve Naroffvoid RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { 487654055232a5ddb9529726e934301b125cb720a273Steve Naroff if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 487754055232a5ddb9529726e934301b125cb720a273Steve Naroff RewriteBlockPointerFunctionArgs(FD); 487854055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 48791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 488054055232a5ddb9529726e934301b125cb720a273Steve Naroff // Handle Variables and Typedefs. 488154055232a5ddb9529726e934301b125cb720a273Steve Naroff SourceLocation DeclLoc = ND->getLocation(); 488254055232a5ddb9529726e934301b125cb720a273Steve Naroff QualType DeclT; 488354055232a5ddb9529726e934301b125cb720a273Steve Naroff if (VarDecl *VD = dyn_cast<VarDecl>(ND)) 488454055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclT = VD->getType(); 488554055232a5ddb9529726e934301b125cb720a273Steve Naroff else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND)) 488654055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclT = TDD->getUnderlyingType(); 488754055232a5ddb9529726e934301b125cb720a273Steve Naroff else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) 488854055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclT = FD->getType(); 48891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else 489054055232a5ddb9529726e934301b125cb720a273Steve Naroff assert(0 && "RewriteBlockPointerDecl(): Decl type not yet handled"); 48911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 489254055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *startBuf = SM->getCharacterData(DeclLoc); 489354055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *endBuf = startBuf; 489454055232a5ddb9529726e934301b125cb720a273Steve Naroff // scan backward (from the decl location) for the end of the previous decl. 489554055232a5ddb9529726e934301b125cb720a273Steve Naroff while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) 489654055232a5ddb9529726e934301b125cb720a273Steve Naroff startBuf--; 48971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 489854055232a5ddb9529726e934301b125cb720a273Steve Naroff // *startBuf != '^' if we are dealing with a pointer to function that 489954055232a5ddb9529726e934301b125cb720a273Steve Naroff // may take block argument types (which will be handled below). 490054055232a5ddb9529726e934301b125cb720a273Steve Naroff if (*startBuf == '^') { 490154055232a5ddb9529726e934301b125cb720a273Steve Naroff // Replace the '^' with '*', computing a negative offset. 490254055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf); 4903d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, 1, "*"); 490454055232a5ddb9529726e934301b125cb720a273Steve Naroff } 490554055232a5ddb9529726e934301b125cb720a273Steve Naroff if (PointerTypeTakesAnyBlockArguments(DeclT)) { 490654055232a5ddb9529726e934301b125cb720a273Steve Naroff // Replace the '^' with '*' for arguments. 490754055232a5ddb9529726e934301b125cb720a273Steve Naroff DeclLoc = ND->getLocation(); 490854055232a5ddb9529726e934301b125cb720a273Steve Naroff startBuf = SM->getCharacterData(DeclLoc); 490954055232a5ddb9529726e934301b125cb720a273Steve Naroff const char *argListBegin, *argListEnd; 491054055232a5ddb9529726e934301b125cb720a273Steve Naroff GetExtentOfArgList(startBuf, argListBegin, argListEnd); 491154055232a5ddb9529726e934301b125cb720a273Steve Naroff while (argListBegin < argListEnd) { 491254055232a5ddb9529726e934301b125cb720a273Steve Naroff if (*argListBegin == '^') { 491354055232a5ddb9529726e934301b125cb720a273Steve Naroff SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf); 4914d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(CaretLoc, 1, "*"); 491554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 491654055232a5ddb9529726e934301b125cb720a273Steve Naroff argListBegin++; 491754055232a5ddb9529726e934301b125cb720a273Steve Naroff } 491854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 491954055232a5ddb9529726e934301b125cb720a273Steve Naroff return; 492054055232a5ddb9529726e934301b125cb720a273Steve Naroff} 492154055232a5ddb9529726e934301b125cb720a273Steve Naroff 4922d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 4923d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: 4924d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, 4925d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// struct Block_byref_id_object *src) { 4926d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// _Block_object_assign (&_dest->object, _src->object, 4927d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 4928d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // object 4929d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// _Block_object_assign(&_dest->object, _src->object, 4930d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 4931d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // block 4932d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// } 4933d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// And: 4934d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { 4935d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// _Block_object_dispose(_src->object, 4936d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 4937d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // object 4938d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// _Block_object_dispose(_src->object, 4939d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 4940d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// [|BLOCK_FIELD_IS_WEAK]) // block 4941d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// } 4942d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 4943ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanianstd::string RewriteObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, 4944ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian int flag) { 4945d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian std::string S; 49461211a71912f263f6991eebfc27a8421a8800b9ecBenjamin Kramer if (CopyDestroyCache.count(flag)) 4947d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian return S; 4948ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian CopyDestroyCache.insert(flag); 4949ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S = "static void __Block_byref_id_object_copy_"; 4950ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += utostr(flag); 4951ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += "(void *dst, void *src) {\n"; 4952ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian 4953d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian // offset into the object pointer is computed as: 4954d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian // void * + void* + int + int + void* + void * 4955d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian unsigned IntSize = 4956d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 4957d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian unsigned VoidPtrSize = 4958d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); 4959d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 4960d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/8; 4961d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += " _Block_object_assign((char*)dst + "; 4962d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(offset); 4963d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += ", *(void * *) ((char*)src + "; 4964d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(offset); 4965d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += "), "; 4966d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(flag); 4967d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += ");\n}\n"; 4968d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 4969ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += "static void __Block_byref_id_object_dispose_"; 4970ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += utostr(flag); 4971ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian S += "(void *src) {\n"; 4972d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += " _Block_object_dispose(*(void * *) ((char*)src + "; 4973d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(offset); 4974d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += "), "; 4975d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += utostr(flag); 4976d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian S += ");\n}\n"; 4977d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian return S; 4978d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian} 4979d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian 498052b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// RewriteByRefVar - For each __block typex ND variable this routine transforms 498152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// the declaration into: 498252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// struct __Block_byref_ND { 498352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// void *__isa; // NULL for everything except __weak pointers 498452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// struct __Block_byref_ND *__forwarding; 498552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// int32_t __flags; 498652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// int32_t __size; 4987d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// void *__Block_byref_id_object_copy; // If variable is __block ObjC object 4988d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian/// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object 498952b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// typex ND; 499052b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// }; 499152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// 499252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// It then replaces declaration of ND variable with: 499352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 499452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// __size=sizeof(struct __Block_byref_ND), 499552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// ND=initializer-if-any}; 499652b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// 499752b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian/// 499852b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanianvoid RewriteObjC::RewriteByRefVar(VarDecl *ND) { 4999abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian // Insert declaration for the function in which block literal is 5000abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian // used. 5001abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian if (CurFunctionDeclToDeclareForBlock) 5002abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian RewriteBlockLiteralFunctionDecl(CurFunctionDeclToDeclareForBlock); 50032086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian int flag = 0; 50042086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian int isa = 0; 500552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 5006d64a4f4798907495091daf2b081c3d62d729dca9Fariborz Jahanian if (DeclLoc.isInvalid()) 5007d64a4f4798907495091daf2b081c3d62d729dca9Fariborz Jahanian // If type location is missing, it is because of missing type (a warning). 5008d64a4f4798907495091daf2b081c3d62d729dca9Fariborz Jahanian // Use variable's location which is good for this case. 5009d64a4f4798907495091daf2b081c3d62d729dca9Fariborz Jahanian DeclLoc = ND->getLocation(); 501052b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian const char *startBuf = SM->getCharacterData(DeclLoc); 50116f0a0a9d2068c2ee9f399c72bf550c307bb76f9aFariborz Jahanian SourceLocation X = ND->getLocEnd(); 50126f0a0a9d2068c2ee9f399c72bf550c307bb76f9aFariborz Jahanian X = SM->getInstantiationLoc(X); 50136f0a0a9d2068c2ee9f399c72bf550c307bb76f9aFariborz Jahanian const char *endBuf = SM->getCharacterData(X); 501452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian std::string Name(ND->getNameAsString()); 5015a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian std::string ByrefType; 5016a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 501752b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " {\n"; 501852b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " void *__isa;\n"; 5019a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 5020a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += " *__forwarding;\n"; 502152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " int __flags;\n"; 502252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " int __size;\n"; 5023d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian // Add void *__Block_byref_id_object_copy; 5024d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian // void *__Block_byref_id_object_dispose; if needed. 5025f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian QualType Ty = ND->getType(); 5026f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty); 5027f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian if (HasCopyAndDispose) { 5028d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; 5029d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; 5030f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian } 5031f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian 5032f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian Ty.getAsStringInternal(Name, Context->PrintingPolicy); 503352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " " + Name + ";\n"; 503452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += "};\n"; 503552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian // Insert this type in global scope. It is needed by helper function. 5036dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian SourceLocation FunLocStart; 5037dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian if (CurFunctionDef) 5038dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian FunLocStart = CurFunctionDef->getTypeSpecStartLoc(); 5039dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian else { 5040dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); 5041dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian FunLocStart = CurMethodDef->getLocStart(); 5042dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian } 5043d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, ByrefType); 50442086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian if (Ty.isObjCGCWeak()) { 50452086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian flag |= BLOCK_FIELD_IS_WEAK; 50462086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian isa = 1; 50472086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian } 50482086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian 5049d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian if (HasCopyAndDispose) { 5050ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian flag = BLOCK_BYREF_CALLER; 5051ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian QualType Ty = ND->getType(); 5052ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. 5053ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian if (Ty->isBlockPointerType()) 5054ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian flag |= BLOCK_FIELD_IS_BLOCK; 5055ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian else 5056ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian flag |= BLOCK_FIELD_IS_OBJECT; 5057ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); 5058d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian if (!HF.empty()) 5059d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(FunLocStart, HF); 5060d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 506152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian 506252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian // struct __Block_byref_ND ND = 506352b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 506452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian // initializer-if-any}; 506552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian bool hasInit = (ND->getInit() != 0); 5066e1f84f8e4cd02347ab0e74eb8f328b3bcacb369cFariborz Jahanian unsigned flags = 0; 5067e1f84f8e4cd02347ab0e74eb8f328b3bcacb369cFariborz Jahanian if (HasCopyAndDispose) 5068e1f84f8e4cd02347ab0e74eb8f328b3bcacb369cFariborz Jahanian flags |= BLOCK_HAS_COPY_DISPOSE; 506952b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian Name = ND->getNameAsString(); 5070a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType.clear(); 5071a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 50722663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian std::string ForwardingCastType("("); 50732663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian ForwardingCastType += ByrefType + " *)"; 507452b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian if (!hasInit) { 50752086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian ByrefType += " " + Name + " = {(void*)"; 50762086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian ByrefType += utostr(isa); 50772663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 5078ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flags); 5079f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ByrefType += ", "; 5080a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += "sizeof("; 5081a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 5082a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += ")"; 5083d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian if (HasCopyAndDispose) { 5084ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += ", __Block_byref_id_object_copy_"; 5085ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flag); 5086ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += ", __Block_byref_id_object_dispose_"; 5087ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flag); 5088d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 508952b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += "};\n"; 5090d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), ByrefType); 509152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian } 509252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian else { 5093dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian SourceLocation startLoc; 5094dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian Expr *E = ND->getInit(); 5095dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 5096dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian startLoc = ECE->getLParenLoc(); 5097dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian else 5098dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian startLoc = E->getLocStart(); 5099791b10d03570ca8c5d3e344cc09900d1a8313999Fariborz Jahanian startLoc = SM->getInstantiationLoc(startLoc); 5100dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian endBuf = SM->getCharacterData(startLoc); 5101dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian 510252b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian ByrefType += " " + Name; 5103dfa4fa0fc5b78a91c74db84fce305771c2038229Fariborz Jahanian ByrefType += " = {(void*)"; 51042086d544d38f2611f2fba034e25833a47c81fb21Fariborz Jahanian ByrefType += utostr(isa); 51052663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 5106ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flags); 5107f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ByrefType += ", "; 5108a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += "sizeof("; 5109a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian RewriteByRefString(ByrefType, Name, ND); 5110a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian ByrefType += "), "; 5111d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian if (HasCopyAndDispose) { 5112ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += "__Block_byref_id_object_copy_"; 5113ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flag); 5114ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += ", __Block_byref_id_object_dispose_"; 5115ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += utostr(flag); 5116ab10b2ebad09c283ccab0ef043118b3cf0166b56Fariborz Jahanian ByrefType += ", "; 5117d2eb1fdb1cfd37a6b93b46161826a23740d185e7Fariborz Jahanian } 5118d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); 5119c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff 5120c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // Complete the newly synthesized compound expression by inserting a right 5121c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // curly brace before the end of the declaration. 5122c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // FIXME: This approach avoids rewriting the initializer expression. It 5123c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // also assumes there is only one declarator. For example, the following 5124c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // isn't currently supported by this routine (in general): 5125c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // 5126c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // double __block BYREFVAR = 1.34, BYREFVAR2 = 1.37; 5127c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff // 5128c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff const char *startBuf = SM->getCharacterData(startLoc); 5129c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff const char *semiBuf = strchr(startBuf, ';'); 5130c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff assert((*semiBuf == ';') && "RewriteByRefVar: can't find ';'"); 5131c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff SourceLocation semiLoc = 5132c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff startLoc.getFileLocWithOffset(semiBuf-startBuf); 5133c5143c538783a2834cfdc3d29db0ff76e857818fSteve Naroff 5134d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(semiLoc, "}"); 513552b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian } 51361be6b460d5aa4dda4274a15eeba824dfd4ad10d0Fariborz Jahanian return; 51371be6b460d5aa4dda4274a15eeba824dfd4ad10d0Fariborz Jahanian} 51381be6b460d5aa4dda4274a15eeba824dfd4ad10d0Fariborz Jahanian 51391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpvoid RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { 514054055232a5ddb9529726e934301b125cb720a273Steve Naroff // Add initializers for any closure decl refs. 514154055232a5ddb9529726e934301b125cb720a273Steve Naroff GetBlockDeclRefExprs(Exp->getBody()); 514254055232a5ddb9529726e934301b125cb720a273Steve Naroff if (BlockDeclRefs.size()) { 514354055232a5ddb9529726e934301b125cb720a273Steve Naroff // Unique all "by copy" declarations. 514454055232a5ddb9529726e934301b125cb720a273Steve Naroff for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 5145bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (!BlockDeclRefs[i]->isByRef()) { 5146bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 5147bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 5148bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); 5149bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian } 5150bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian } 515154055232a5ddb9529726e934301b125cb720a273Steve Naroff // Unique all "by ref" declarations. 515254055232a5ddb9529726e934301b125cb720a273Steve Naroff for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 515354055232a5ddb9529726e934301b125cb720a273Steve Naroff if (BlockDeclRefs[i]->isByRef()) { 5154bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 5155bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 5156bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); 5157bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian } 515854055232a5ddb9529726e934301b125cb720a273Steve Naroff } 515954055232a5ddb9529726e934301b125cb720a273Steve Naroff // Find any imported blocks...they will need special attention. 516054055232a5ddb9529726e934301b125cb720a273Steve Naroff for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 51614fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian if (BlockDeclRefs[i]->isByRef() || 51624fcc4fd1adf272450bdecab7f9133ae2f0b8aa19Fariborz Jahanian BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 51635b011b050e764fe1c2a38bd81b386fc6e66eeb93Fariborz Jahanian BlockDeclRefs[i]->getType()->isBlockPointerType()) 516454055232a5ddb9529726e934301b125cb720a273Steve Naroff ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); 516554055232a5ddb9529726e934301b125cb720a273Steve Naroff } 516654055232a5ddb9529726e934301b125cb720a273Steve Naroff} 516754055232a5ddb9529726e934301b125cb720a273Steve Naroff 5168fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffFunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(const char *name) { 5169fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff IdentifierInfo *ID = &Context->Idents.get(name); 517072564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); 51711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return FunctionDecl::Create(*Context, TUDecl,SourceLocation(), 517216573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor ID, FType, 0, FunctionDecl::Extern, 517316573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor FunctionDecl::None, false, false); 5174fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5175fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 51765e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz JahanianStmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, 51775e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian const llvm::SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) { 5178fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Blocks.push_back(Exp); 5179fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5180fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CollectBlockDeclRefInfo(Exp); 51815e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 51825e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // Add inner imported variables now used in current block. 51835e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian int countOfInnerDecls = 0; 51841276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian if (!InnerBlockDeclRefs.empty()) { 51851276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { 51861276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i]; 51871276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian ValueDecl *VD = Exp->getDecl(); 51881276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) { 51895e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // We need to save the copied-in variables in nested 51905e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // blocks because it is needed at the end for some of the API generations. 51915e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian // See SynthesizeBlockLiterals routine. 51921276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 51931276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockDeclRefs.push_back(Exp); 51941276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockByCopyDeclsPtrSet.insert(VD); 51951276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockByCopyDecls.push_back(VD); 51961276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian } 51971276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) { 51981276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 51991276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockDeclRefs.push_back(Exp); 52001276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockByRefDeclsPtrSet.insert(VD); 52011276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian BlockByRefDecls.push_back(VD); 52021276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian } 5203f89c4270c94ddd966819fe6b8306aa572d1e5d83Fariborz Jahanian } 52041276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian // Find any imported blocks...they will need special attention. 52051276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) 52061276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian if (InnerBlockDeclRefs[i]->isByRef() || 52071276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 52081276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) 52091276bfe0cec18a8b07226797f410b7506005269dFariborz Jahanian ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); 52105e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian } 52115e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian InnerDeclRefsCount.push_back(countOfInnerDecls); 52125e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 5213fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string FuncName; 52141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5215fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (CurFunctionDef) 5216077bf5e2f48acfa9e7d69429b6e4ba86ea14896dChris Lattner FuncName = CurFunctionDef->getNameAsString(); 5217e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian else if (CurMethodDef) 5218e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian BuildUniqueMethodName(FuncName, CurMethodDef); 5219e61a1d4c57bbce3dfaa191a4b4de48ad79ac0b83Fariborz Jahanian else if (GlobalVarDecl) 5220d9d22dd9c94618490dbffb0e2caf222530ca39d3Chris Lattner FuncName = std::string(GlobalVarDecl->getNameAsString()); 52211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5222fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string BlockNumber = utostr(Blocks.size()-1); 52231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5224fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string Tag = "__" + FuncName + "_block_impl_" + BlockNumber; 5225fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; 52261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5227fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Get a pointer to the function type so we can cast appropriately. 52281f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType()); 52291f90622e9d24064164df1608ea125d0ed451ac68Fariborz Jahanian QualType FType = Context->getPointerType(BFT); 5230fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5231fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff FunctionDecl *FD; 5232fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Expr *NewRep; 52331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5234fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Simulate a contructor call... 5235fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff FD = SynthBlockInitFunctionDecl(Tag.c_str()); 52368189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, SourceLocation()); 52371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5238fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff llvm::SmallVector<Expr*, 4> InitExprs; 52391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5240fdc0372eda30952b03f3fd4269dbc4b2acfdfa55Steve Naroff // Initialize the block function. 5241fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff FD = SynthBlockInitFunctionDecl(Func.c_str()); 52428189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), 52438189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek SourceLocation()); 52449d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 52459d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, Arg); 52461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump InitExprs.push_back(castExpr); 52471eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 524801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff // Initialize the block descriptor. 524901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; 525001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 525101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 525201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff &Context->Idents.get(DescData.c_str()), 525301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Context->VoidPtrTy, 0, 525416573fa9705b546b7597c273b25b85d6321e2b33Douglas Gregor VarDecl::Static, VarDecl::None); 525501aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff UnaryOperator *DescRefExpr = new (Context) UnaryOperator( 525601aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff new (Context) DeclRefExpr(NewVD, 525701aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Context->VoidPtrTy, SourceLocation()), 525801aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff UnaryOperator::AddrOf, 525901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff Context->getPointerType(Context->VoidPtrTy), 526001aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff SourceLocation()); 526101aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff InitExprs.push_back(DescRefExpr); 526201aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff 5263fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Add initializers for any closure decl refs. 5264fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BlockDeclRefs.size()) { 5265fdc0372eda30952b03f3fd4269dbc4b2acfdfa55Steve Naroff Expr *Exp; 5266fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Output all "by copy" declarations. 5267bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 5268fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff E = BlockByCopyDecls.end(); I != E; ++I) { 5269fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (isObjCType((*I)->getType())) { 5270fdc0372eda30952b03f3fd4269dbc4b2acfdfa55Steve Naroff // FIXME: Conform to ABI ([[obj retain] autorelease]). 52718ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); 52728189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); 5273a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian if (HasLocalVariableExternalStorage(*I)) { 5274a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian QualType QT = (*I)->getType(); 5275a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian QT = Context->getPointerType(QT); 5276a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, QT, 5277a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian SourceLocation()); 5278a5a7987394ca15334c03b7e168677a8056561062Fariborz Jahanian } 527901f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff } else if (isTopLevelBlockPointerType((*I)->getType())) { 52808ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); 52818189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Arg = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); 52829d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 52839d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall CastExpr::CK_Unknown, Arg); 5284fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } else { 52858ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); 52868189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); 52876cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(*I)) { 52886cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QualType QT = (*I)->getType(); 52896cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian QT = Context->getPointerType(QT); 52906cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, QT, 52916cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian SourceLocation()); 52926cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian } 52936cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian 5294fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 52951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump InitExprs.push_back(Exp); 5296fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5297fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Output all "by ref" declarations. 5298bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 5299fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff E = BlockByRefDecls.end(); I != E; ++I) { 53002663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian ValueDecl *ND = (*I); 53012663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian std::string Name(ND->getNameAsString()); 53022663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian std::string RecName; 53032663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian RewriteByRefString(RecName, Name, ND); 53042663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 53052663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian + sizeof("struct")); 5306465d41b92b2c862f3062c412a0538db65c6a2661Abramo Bagnara RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 53072663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian SourceLocation(), II); 53082663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); 53092663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 53102663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian 53118ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); 53128189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); 53138189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, 53141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Context->getPointerType(Exp->getType()), 5315fdc0372eda30952b03f3fd4269dbc4b2acfdfa55Steve Naroff SourceLocation()); 53162663f527c2717295fbaed4715945b879ad68f4cfFariborz Jahanian Exp = NoTypeInfoCStyleCastExpr(Context, castT, CastExpr::CK_Unknown, Exp); 53171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump InitExprs.push_back(Exp); 5318fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 531901aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff } 5320ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian if (ImportedBlockDecls.size()) { 5321ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR 5322ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR); 532301aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff unsigned IntSize = 532401aec11c8cace2b9b22531627970d8bbdbac0c1cSteve Naroff static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 5325ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian Expr *FlagExp = new (Context) IntegerLiteral(llvm::APInt(IntSize, flag), 5326ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian Context->IntTy, SourceLocation()); 5327ff1278809e62d1da22da171752cc5f07734bcf0cFariborz Jahanian InitExprs.push_back(FlagExp); 5328fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5329668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(), 5330668bf91d31265b6ea8c3eb854ba450857701f269Ted Kremenek FType, SourceLocation()); 53318189cde56b4f6f938cd65f53c932fe1860d0204cTed Kremenek NewRep = new (Context) UnaryOperator(NewRep, UnaryOperator::AddrOf, 53321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump Context->getPointerType(NewRep->getType()), 5333fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation()); 53349d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CastExpr::CK_Unknown, 53359d125033a9853f3b572a4c9e2f9e2d4e5e346973John McCall NewRep); 5336fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff BlockDeclRefs.clear(); 5337fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff BlockByRefDecls.clear(); 5338bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByRefDeclsPtrSet.clear(); 5339fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff BlockByCopyDecls.clear(); 5340bab71685568085b635f077ee5720d22dffab84beFariborz Jahanian BlockByCopyDeclsPtrSet.clear(); 5341fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff ImportedBlockDecls.clear(); 5342fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return NewRep; 5343fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5344fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5345fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff//===----------------------------------------------------------------------===// 5346fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff// Function Body / Expression rewriting 5347fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff//===----------------------------------------------------------------------===// 5348fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5349c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// This is run as a first "pass" prior to RewriteFunctionBodyOrGlobalInitializer(). 5350c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// The allows the main rewrite loop to associate all ObjCPropertyRefExprs with 5351c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// their respective BinaryOperator. Without this knowledge, we'd need to rewrite 5352c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// the ObjCPropertyRefExpr twice (once as a getter, and later as a setter). 5353c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// Since the rewriter isn't capable of rewriting rewritten code, it's important 5354c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff// we get this right. 5355c77a636688e188af7e7a9a05829e542adb48e880Steve Naroffvoid RewriteObjC::CollectPropertySetters(Stmt *S) { 5356c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // Perform a bottom up traversal of all children. 5357c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 5358c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CI != E; ++CI) 5359c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (*CI) 5360c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CollectPropertySetters(*CI); 5361c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff 5362c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { 5363c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (BinOp->isAssignmentOp()) { 5364c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) 5365c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff PropSetters[PRE] = BinOp; 5366c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff } 5367c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff } 5368c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff} 5369c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff 5370fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve NaroffStmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { 53711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 5372fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff isa<DoStmt>(S) || isa<ForStmt>(S)) 5373fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Stmts.push_back(S); 5374fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff else if (isa<ObjCForCollectionStmt>(S)) { 5375fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Stmts.push_back(S); 53764824fcdf37139efa57466a2a5753dd6e5e792ef8Chris Lattner ObjCBcLabelNo.push_back(++BcLabelCount); 5377fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 53781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5379fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceRange OrigStmtRange = S->getSourceRange(); 53801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5381fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Perform a bottom up rewrite of all children. 5382fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); 5383fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CI != E; ++CI) 5384fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (*CI) { 53852b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *newStmt; 53862b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Stmt *S = (*CI); 53872b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 53882b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian Expr *OldBase = IvarRefExpr->getBase(); 53892b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian bool replaced = false; 53902b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian newStmt = RewriteObjCNestedIvarRefExpr(S, replaced); 53912b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (replaced) { 53922b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt)) 53932b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian ReplaceStmt(OldBase, IRE->getBase()); 53942b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian else 53952b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian ReplaceStmt(S, newStmt); 53962b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian } 53972b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian } 53982b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian else 53992b9b0b2c9a7137f46b7cc6a02ca9608f2fcc868dFariborz Jahanian newStmt = RewriteFunctionBodyOrGlobalInitializer(S); 54001eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (newStmt) 5401fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff *CI = newStmt; 5402fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 54031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5404fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { 54055e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian llvm::SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs; 540672952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; 540772952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerContexts.insert(BE->getBlockDecl()); 54086cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ImportedLocalExternalDecls.clear(); 54095e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian GetInnerBlockDeclRefExprs(BE->getBody(), 541072952fc11f80c975492a2a1e0f6e3601c5252e0aFariborz Jahanian InnerBlockDeclRefs, InnerContexts); 5411fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Rewrite the block body in place. 5412fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); 54136cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian ImportedLocalExternalDecls.clear(); 5414fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Now we snarf the rewritten text and stash it away for later use. 54156a12a14a529a79524e17889046c7098b80a73c49Ted Kremenek std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); 54168e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff RewrittenBlockExprs[BE] = Str; 54171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54185e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); 54195e49b2f3e0bbc583076fe8af00dff06bcba06dafFariborz Jahanian 5420fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff //blockTranscribed->dump(); 54218e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff ReplaceStmt(S, blockTranscribed); 5422fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return blockTranscribed; 5423fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5424fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Handle specific things. 5425fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) 5426fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteAtEncode(AtEncode); 54271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5428c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(S)) { 5429c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff BinaryOperator *BinOp = PropSetters[PropRefExpr]; 5430c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff if (BinOp) { 5431c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // Because the rewriter doesn't allow us to rewrite rewritten code, 5432c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff // we need to rewrite the right hand side prior to rewriting the setter. 5433b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff DisableReplaceStmt = true; 5434b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // Save the source range. Even if we disable the replacement, the 5435b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // rewritten node will have been inserted into the tree. If the synthesized 5436b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // node is at the 'end', the rewriter will fail. Consider this: 54371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // self.errorHandler = handler ? handler : 5438b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff // ^(NSURL *errorURL, NSError *error) { return (BOOL)1; }; 5439b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff SourceRange SrcRange = BinOp->getSourceRange(); 5440c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS()); 5441b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff DisableReplaceStmt = false; 54424c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54434c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // Unlike the main iterator, we explicily avoid changing 'BinOp'. If 54444c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // we changed the RHS of BinOp, the rewriter would fail (since it needs 54454c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // to see the original expression). Consider this example: 54464c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54474c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // Foo *obj1, *obj2; 54484c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54494c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // obj1.i = [obj2 rrrr]; 54504c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54514c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 'BinOp' for the previous expression looks like: 54524c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54534c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (BinaryOperator 0x231ccf0 'int' '=' 54544c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (ObjCPropertyRefExpr 0x231cc70 'int' Kind=PropertyRef Property="i" 54554c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (DeclRefExpr 0x231cc50 'Foo *' Var='obj1' 0x231cbb0)) 54564c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (ObjCMessageExpr 0x231ccb0 'int' selector=rrrr 54574c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (DeclRefExpr 0x231cc90 'Foo *' Var='obj2' 0x231cbe0))) 54584c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54594c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 'newStmt' represents the rewritten message expression. For example: 54604c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54614c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (CallExpr 0x231d300 'id':'struct objc_object *' 54624c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (ParenExpr 0x231d2e0 'int (*)(id, SEL)' 54634c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (CStyleCastExpr 0x231d2c0 'int (*)(id, SEL)' 54644c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (CStyleCastExpr 0x231d220 'void *' 54654c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0)))) 54664c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54674c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // Note that 'newStmt' is passed to RewritePropertySetter so that it 54684c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // can be used as the setter argument. ReplaceStmt() will still 'see' 54694c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // the original RHS (since we haven't altered BinOp). 54704c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 54711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // This implies the Rewrite* routines can no longer delete the original 54724c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // node. As a result, we now leak the original AST nodes. 54734c3580e5f9d1804fa08fecca76ad5089bc9965feSteve Naroff // 5474b619d957b020744bb6bfdd1cef8169d8042df43eSteve Naroff return RewritePropertySetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange); 5475c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff } else { 5476c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff return RewritePropertyGetter(PropRefExpr); 547715f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff } 547815f081de2c8ac7deadf5d938b458b20732230cd9Steve Naroff } 5479fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) 5480fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteAtSelector(AtSelector); 54811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5482fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) 5483fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCStringLiteral(AtString); 54841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5485fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { 5486c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff#if 0 5487fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Before we rewrite it, put the original message expression in a comment. 5488fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation startLoc = MessExpr->getLocStart(); 5489fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff SourceLocation endLoc = MessExpr->getLocEnd(); 54901eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5491fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff const char *startBuf = SM->getCharacterData(startLoc); 5492fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff const char *endBuf = SM->getCharacterData(endLoc); 54931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5494fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string messString; 5495fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff messString += "// "; 5496fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff messString.append(startBuf, endBuf-startBuf+1); 5497fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff messString += "\n"; 54981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 54991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // FIXME: Missing definition of 5500fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // InsertText(clang::SourceLocation, char const*, unsigned int). 5501fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // InsertText(startLoc, messString.c_str(), messString.size()); 5502fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Tried this, but it didn't work either... 5503fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); 5504c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff#endif 5505fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteMessageExpr(MessExpr); 5506fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 55071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5508fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) 5509fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCTryStmt(StmtTry); 5510fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5511fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) 5512fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCSynchronizedStmt(StmtTry); 5513fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5514fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) 5515fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCThrowStmt(StmtThrow); 55161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5517fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) 5518fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteObjCProtocolExpr(ProtocolExp); 55191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (ObjCForCollectionStmt *StmtForCollection = 5521fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff dyn_cast<ObjCForCollectionStmt>(S)) 55221eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump return RewriteObjCForCollectionStmt(StmtForCollection, 5523fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff OrigStmtRange.getEnd()); 5524fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BreakStmt *StmtBreakStmt = 5525fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff dyn_cast<BreakStmt>(S)) 5526fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteBreakStmt(StmtBreakStmt); 5527fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ContinueStmt *StmtContinueStmt = 5528fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff dyn_cast<ContinueStmt>(S)) 5529fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return RewriteContinueStmt(StmtContinueStmt); 55301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls 5532fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // and cast exprs. 5533fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 5534fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // FIXME: What we're doing here is modifying the type-specifier that 5535fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // precedes the first Decl. In the future the DeclGroup should have 55361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // a separate type-specifier that we can rewrite. 55373d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // NOTE: We need to avoid rewriting the DeclStmt if it is within 55383d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // the context of an ObjCForCollectionStmt. For example: 55393d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // NSArray *someArray; 55403d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // for (id <FooProtocol> index in someArray) ; 55413d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // This is because RewriteObjCForCollectionStmt() does textual rewriting 55423d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff // and it depends on the original text locations/positions. 5543b2041de2eb3e44d04cb8c62c4369314af4fd6a90Benjamin Kramer if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 55443d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); 55451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5546fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Blocks rewrite rules. 5547fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 5548fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff DI != DE; ++DI) { 55494afa39deaa245592977136d367251ee2c173dd8dDouglas Gregor Decl *SD = *DI; 5550fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { 555101f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(ND->getType())) 5552fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteBlockPointerDecl(ND); 55531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (ND->getType()->isFunctionPointerType()) 5554fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CheckFunctionPointerDecl(ND->getType(), ND); 55554c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { 5556a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian if (VD->hasAttr<BlocksAttr>()) { 5557a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian static unsigned uniqueByrefDeclCount = 0; 5558a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian assert(!BlockByRefDeclNo.count(ND) && 5559a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); 5560a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; 556152b08f2c8a65c059cb2123fa0fd6317b829416deFariborz Jahanian RewriteByRefVar(VD); 5562a73165e47aefbea60312d284343660c9c962c9c3Fariborz Jahanian } 55634c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian else 55644c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian RewriteTypeOfDecl(VD); 55654c863ef92c2b74572090da245c87e1487b0b596cFariborz Jahanian } 5566fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5567fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { 556801f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 5569fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteBlockPointerDecl(TD); 55701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (TD->getUnderlyingType()->isFunctionPointerType()) 5571fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 5572fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5573fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5574fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 55751eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5576fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) 5577fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteObjCQualifiedInterfaceTypes(CE); 55781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 55791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 5580fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff isa<DoStmt>(S) || isa<ForStmt>(S)) { 5581fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff assert(!Stmts.empty() && "Statement stack is empty"); 55821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 55831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 5584fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff && "Statement stack mismatch"); 5585fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Stmts.pop_back(); 5586fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5587fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Handle blocks rewriting. 5588fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) { 5589fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (BDRE->isByRef()) 5590621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff return RewriteBlockDeclRefExpr(BDRE); 5591fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5592f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 5593f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian ValueDecl *VD = DRE->getDecl(); 5594f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian if (VD->hasAttr<BlocksAttr>()) 5595f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian return RewriteBlockDeclRefExpr(DRE); 55966cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian if (HasLocalVariableExternalStorage(VD)) 55976cb6eb4c792b504ad652d9230640656852e18ee9Fariborz Jahanian return RewriteLocalVariableExternalStorage(DRE); 5598f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian } 5599f381cc90d6cfa0966ddf791db57a6ed6c2462b5dFariborz Jahanian 5600fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 5601aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff if (CE->getCallee()->getType()->isBlockPointerType()) { 56028a9e170efd32855377bc7fc5f7ea431ec4f8802eFariborz Jahanian Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); 5603aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff ReplaceStmt(S, BlockCall); 5604aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff return BlockCall; 5605aa4d5ae6c450fdbe207cdb12373fc026376ece42Steve Naroff } 5606fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5607b2f9e516327310d95840d442416084508f80c183Steve Naroff if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) { 5608fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteCastExpr(CE); 5609fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5610fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff#if 0 5611fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 5612906082edf2aea1c6de2926f93a8d7121e49d2a54Sebastian Redl CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), 5613906082edf2aea1c6de2926f93a8d7121e49d2a54Sebastian Redl ICE->getSubExpr(), 5614906082edf2aea1c6de2926f93a8d7121e49d2a54Sebastian Redl SourceLocation()); 5615fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Get the new text. 5616fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff std::string SStr; 5617fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff llvm::raw_string_ostream Buf(SStr); 56183a9eb44f2906e44ca29ae2d9df56fb9824ef7d05Eli Friedman Replacement->printPretty(Buf, *Context); 5619fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff const std::string &Str = Buf.str(); 5620fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5621fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff printf("CAST = %s\n", &Str[0]); 5622fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size()); 5623fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff delete S; 5624fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return Replacement; 5625fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5626fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff#endif 5627fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Return this stmt unmodified. 5628fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return S; 5629fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5630fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 56313d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroffvoid RewriteObjC::RewriteRecordBody(RecordDecl *RD) { 56323d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff for (RecordDecl::field_iterator i = RD->field_begin(), 56333d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff e = RD->field_end(); i != e; ++i) { 56343d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff FieldDecl *FD = *i; 56353d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff if (isTopLevelBlockPointerType(FD->getType())) 56363d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteBlockPointerDecl(FD); 56373d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff if (FD->getType()->isObjCQualifiedIdType() || 56383d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff FD->getType()->isObjCQualifiedInterfaceType()) 56393d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteObjCQualifiedInterfaceTypes(FD); 56403d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff } 56413d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff} 56423d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff 5643fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// HandleDeclInMainFile - This is called for each top-level decl defined in the 5644fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff/// main file of the input. 5645fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroffvoid RewriteObjC::HandleDeclInMainFile(Decl *D) { 5646fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 5647cb73530987a22a6877039b9404b29aba3bf226e0Steve Naroff if (FD->isOverloadedOperator()) 5648cb73530987a22a6877039b9404b29aba3bf226e0Steve Naroff return; 56491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5650fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Since function prototypes don't have ParmDecl's, we check the function 5651fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // prototype. This enables us to rewrite function declarations and 5652fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // definitions using the same code. 565372564e73277e29f6db3305d1f27ba408abb7ed88Douglas Gregor RewriteBlocksInFunctionProtoType(FD->getType(), FD); 5654fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5655d3a413d3b8eb39bcee5944bc545d9997c1abe492Sebastian Redl // FIXME: If this should support Obj-C++, support CXXTryStmt 56565f1bfc10a12d9759444eb433f52a85d2e0058967Argyrios Kyrtzidis if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { 5657fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CurFunctionDef = FD; 5658abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = FD; 5659c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CollectPropertySetters(Body); 56608599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = Body; 5661eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek Body = 5662eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 5663eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek FD->setBody(Body); 56648599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = 0; 56658599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (PropParentMap) { 56668599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff delete PropParentMap; 56678599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropParentMap = 0; 56688599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 5669fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // This synthesizes and inserts the block "impl" struct, invoke function, 5670fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // and any copy/dispose helper functions. 5671fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff InsertBlockLiteralsWithinFunction(FD); 5672fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CurFunctionDef = 0; 5673abfd83e74ca8a7553e375dd4631d2570f33648b4Fariborz Jahanian CurFunctionDeclToDeclareForBlock = 0; 56741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 5675fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 5676fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5677fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { 56786fb0aee4f9dc261bbec72e1283ad8dc0557a6d96Argyrios Kyrtzidis if (CompoundStmt *Body = MD->getCompoundBody()) { 5679fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CurMethodDef = MD; 5680c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CollectPropertySetters(Body); 56818599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = Body; 5682eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek Body = 5683eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 5684eaab20669b6a9910a5deb0110fdd8f7581d86a36Ted Kremenek MD->setBody(Body); 56858599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = 0; 56868599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (PropParentMap) { 56878599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff delete PropParentMap; 56888599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropParentMap = 0; 56898599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 5690fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff InsertBlockLiteralsWithinMethod(MD); 5691fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CurMethodDef = 0; 5692fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5693fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5694fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (ObjCImplementationDecl *CI = dyn_cast<ObjCImplementationDecl>(D)) 5695fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff ClassImplementation.push_back(CI); 5696fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff else if (ObjCCategoryImplDecl *CI = dyn_cast<ObjCCategoryImplDecl>(D)) 5697fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CategoryImplementation.push_back(CI); 5698fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff else if (ObjCClassDecl *CD = dyn_cast<ObjCClassDecl>(D)) 5699fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteForwardClassDecl(CD); 5700fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { 5701fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteObjCQualifiedInterfaceTypes(VD); 570201f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(VD->getType())) 5703fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteBlockPointerDecl(VD); 57048e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff else if (VD->getType()->isFunctionPointerType()) { 5705fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CheckFunctionPointerDecl(VD->getType(), VD); 5706fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (VD->getInit()) { 5707b2f9e516327310d95840d442416084508f80c183Steve Naroff if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 5708fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteCastExpr(CE); 5709fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5710fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 57113d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff } else if (VD->getType()->isRecordType()) { 57123d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl(); 57133d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff if (RD->isDefinition()) 57143d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteRecordBody(RD); 5715fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 57168e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff if (VD->getInit()) { 57178e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff GlobalVarDecl = VD; 5718c77a636688e188af7e7a9a05829e542adb48e880Steve Naroff CollectPropertySetters(VD->getInit()); 57198599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = VD->getInit(); 57208e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); 57218599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff CurrentBody = 0; 57228599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff if (PropParentMap) { 57238599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff delete PropParentMap; 57248599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff PropParentMap = 0; 57258599e7a394e7ed44a32dfe64733125e095e3f28cSteve Naroff } 57261eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), 57278ec03f58c33c33a917f54bb7f2cd61b6d7ffe0caChris Lattner VD->getNameAsCString()); 57288e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff GlobalVarDecl = 0; 57298e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff 57308e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff // This is needed for blocks. 5731b2f9e516327310d95840d442416084508f80c183Steve Naroff if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 57328e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff RewriteCastExpr(CE); 57338e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff } 57348e2f57ad06d73a6c2cacf0167a3b9e244439a9f9Steve Naroff } 5735fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 5736fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5737fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { 573801f2ffacc427de6bef08fe138e8cae82ba1b30a3Steve Naroff if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 5739fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteBlockPointerDecl(TD); 57401eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump else if (TD->getUnderlyingType()->isFunctionPointerType()) 5741fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 5742fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 5743fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5744fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { 57453d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff if (RD->isDefinition()) 57463d7e7865bd0863fcf36aee14d8911b785dde57ddSteve Naroff RewriteRecordBody(RD); 5747fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 5748fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5749fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Nothing yet. 5750fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5751fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff 5752dacbc5d46aaeea817742b8c76c987b87d2490c85Chris Lattnervoid RewriteObjC::HandleTranslationUnit(ASTContext &C) { 5753fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff if (Diags.hasErrorOccurred()) 5754fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff return; 57551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5756fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff RewriteInclude(); 57571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 5758621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Here's a great place to add any extra declarations that may be needed. 5759621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff // Write out meta data for each @protocol(<expr>). 57601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 5761621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff E = ProtocolExprDecls.end(); I != E; ++I) 5762621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff RewriteObjCProtocolMetaData(*I, "", "", Preamble); 5763621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 5764d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); 57650aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff if (ClassImplementation.size() || CategoryImplementation.size()) 57660aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff RewriteImplementations(); 5767621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff 5768fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // Get the buffer corresponding to MainFileID. If we haven't changed it, then 5769fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff // we are done. 57701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump if (const RewriteBuffer *RewriteBuf = 5771fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff Rewrite.getRewriteBufferFor(MainFileID)) { 5772fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff //printf("Changed:\n"); 5773fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 5774fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } else { 5775d999b3736ce2646ae0711416b421d906298764dbBenjamin Kramer llvm::errs() << "No changes\n"; 5776fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff } 5777ace6625f236af4fc81d87d63d79d7819944524dcSteve Naroff 5778621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff if (ClassImplementation.size() || CategoryImplementation.size() || 5779621edce9cd7d4e06979daf911cc306350619f33bSteve Naroff ProtocolExprDecls.size()) { 57800aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff // Rewrite Objective-c meta data* 57810aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff std::string ResultStr; 57820aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff SynthesizeMetaDataIntoBuffer(ResultStr); 57830aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff // Emit metadata. 57840aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff *OutFile << ResultStr; 57850aab796da21bfc45381d3ce76c795710cb97acfcSteve Naroff } 5786fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff OutFile->flush(); 5787fa15fd9db405f2d0a9811e94a671f7d7bc282385Steve Naroff} 5788