clang API Documentation
00001 //===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Hacks and fun related to the code rewriter. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/Rewrite/ASTConsumers.h" 00015 #include "clang/Rewrite/Rewriter.h" 00016 #include "clang/AST/AST.h" 00017 #include "clang/AST/ASTConsumer.h" 00018 #include "clang/AST/ParentMap.h" 00019 #include "clang/Basic/SourceManager.h" 00020 #include "clang/Basic/IdentifierTable.h" 00021 #include "clang/Basic/Diagnostic.h" 00022 #include "clang/Lex/Lexer.h" 00023 #include "llvm/Support/MemoryBuffer.h" 00024 #include "llvm/Support/raw_ostream.h" 00025 #include "llvm/ADT/StringExtras.h" 00026 #include "llvm/ADT/SmallPtrSet.h" 00027 #include "llvm/ADT/OwningPtr.h" 00028 #include "llvm/ADT/DenseSet.h" 00029 00030 using namespace clang; 00031 using llvm::utostr; 00032 00033 namespace { 00034 class RewriteModernObjC : public ASTConsumer { 00035 protected: 00036 00037 enum { 00038 BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 00039 block, ... */ 00040 BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 00041 BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the 00042 __block variable */ 00043 BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 00044 helpers */ 00045 BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 00046 support routines */ 00047 BLOCK_BYREF_CURRENT_MAX = 256 00048 }; 00049 00050 enum { 00051 BLOCK_NEEDS_FREE = (1 << 24), 00052 BLOCK_HAS_COPY_DISPOSE = (1 << 25), 00053 BLOCK_HAS_CXX_OBJ = (1 << 26), 00054 BLOCK_IS_GC = (1 << 27), 00055 BLOCK_IS_GLOBAL = (1 << 28), 00056 BLOCK_HAS_DESCRIPTOR = (1 << 29) 00057 }; 00058 static const int OBJC_ABI_VERSION = 7; 00059 00060 Rewriter Rewrite; 00061 DiagnosticsEngine &Diags; 00062 const LangOptions &LangOpts; 00063 ASTContext *Context; 00064 SourceManager *SM; 00065 TranslationUnitDecl *TUDecl; 00066 FileID MainFileID; 00067 const char *MainFileStart, *MainFileEnd; 00068 Stmt *CurrentBody; 00069 ParentMap *PropParentMap; // created lazily. 00070 std::string InFileName; 00071 raw_ostream* OutFile; 00072 std::string Preamble; 00073 00074 TypeDecl *ProtocolTypeDecl; 00075 VarDecl *GlobalVarDecl; 00076 Expr *GlobalConstructionExp; 00077 unsigned RewriteFailedDiag; 00078 unsigned GlobalBlockRewriteFailedDiag; 00079 // ObjC string constant support. 00080 unsigned NumObjCStringLiterals; 00081 VarDecl *ConstantStringClassReference; 00082 RecordDecl *NSStringRecord; 00083 00084 // ObjC foreach break/continue generation support. 00085 int BcLabelCount; 00086 00087 unsigned TryFinallyContainsReturnDiag; 00088 // Needed for super. 00089 ObjCMethodDecl *CurMethodDef; 00090 RecordDecl *SuperStructDecl; 00091 RecordDecl *ConstantStringDecl; 00092 00093 FunctionDecl *MsgSendFunctionDecl; 00094 FunctionDecl *MsgSendSuperFunctionDecl; 00095 FunctionDecl *MsgSendStretFunctionDecl; 00096 FunctionDecl *MsgSendSuperStretFunctionDecl; 00097 FunctionDecl *MsgSendFpretFunctionDecl; 00098 FunctionDecl *GetClassFunctionDecl; 00099 FunctionDecl *GetMetaClassFunctionDecl; 00100 FunctionDecl *GetSuperClassFunctionDecl; 00101 FunctionDecl *SelGetUidFunctionDecl; 00102 FunctionDecl *CFStringFunctionDecl; 00103 FunctionDecl *SuperContructorFunctionDecl; 00104 FunctionDecl *CurFunctionDef; 00105 00106 /* Misc. containers needed for meta-data rewrite. */ 00107 SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; 00108 SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; 00109 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; 00110 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; 00111 llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCWrittenInterfaces; 00112 llvm::SmallPtrSet<TagDecl*, 32> GlobalDefinedTags; 00113 SmallVector<ObjCInterfaceDecl*, 32> ObjCInterfacesSeen; 00114 /// DefinedNonLazyClasses - List of defined "non-lazy" classes. 00115 SmallVector<ObjCInterfaceDecl*, 8> DefinedNonLazyClasses; 00116 00117 /// DefinedNonLazyCategories - List of defined "non-lazy" categories. 00118 llvm::SmallVector<ObjCCategoryDecl*, 8> DefinedNonLazyCategories; 00119 00120 SmallVector<Stmt *, 32> Stmts; 00121 SmallVector<int, 8> ObjCBcLabelNo; 00122 // Remember all the @protocol(<expr>) expressions. 00123 llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; 00124 00125 llvm::DenseSet<uint64_t> CopyDestroyCache; 00126 00127 // Block expressions. 00128 SmallVector<BlockExpr *, 32> Blocks; 00129 SmallVector<int, 32> InnerDeclRefsCount; 00130 SmallVector<DeclRefExpr *, 32> InnerDeclRefs; 00131 00132 SmallVector<DeclRefExpr *, 32> BlockDeclRefs; 00133 00134 // Block related declarations. 00135 SmallVector<ValueDecl *, 8> BlockByCopyDecls; 00136 llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; 00137 SmallVector<ValueDecl *, 8> BlockByRefDecls; 00138 llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; 00139 llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; 00140 llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; 00141 llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls; 00142 00143 llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; 00144 llvm::DenseMap<ObjCInterfaceDecl *, 00145 llvm::SmallPtrSet<ObjCIvarDecl *, 8> > ReferencedIvars; 00146 00147 // This maps an original source AST to it's rewritten form. This allows 00148 // us to avoid rewriting the same node twice (which is very uncommon). 00149 // This is needed to support some of the exotic property rewriting. 00150 llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; 00151 00152 // Needed for header files being rewritten 00153 bool IsHeader; 00154 bool SilenceRewriteMacroWarning; 00155 bool objc_impl_method; 00156 00157 bool DisableReplaceStmt; 00158 class DisableReplaceStmtScope { 00159 RewriteModernObjC &R; 00160 bool SavedValue; 00161 00162 public: 00163 DisableReplaceStmtScope(RewriteModernObjC &R) 00164 : R(R), SavedValue(R.DisableReplaceStmt) { 00165 R.DisableReplaceStmt = true; 00166 } 00167 ~DisableReplaceStmtScope() { 00168 R.DisableReplaceStmt = SavedValue; 00169 } 00170 }; 00171 void InitializeCommon(ASTContext &context); 00172 00173 public: 00174 llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; 00175 // Top Level Driver code. 00176 virtual bool HandleTopLevelDecl(DeclGroupRef D) { 00177 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 00178 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) { 00179 if (!Class->isThisDeclarationADefinition()) { 00180 RewriteForwardClassDecl(D); 00181 break; 00182 } else { 00183 // Keep track of all interface declarations seen. 00184 ObjCInterfacesSeen.push_back(Class); 00185 break; 00186 } 00187 } 00188 00189 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) { 00190 if (!Proto->isThisDeclarationADefinition()) { 00191 RewriteForwardProtocolDecl(D); 00192 break; 00193 } 00194 } 00195 00196 HandleTopLevelSingleDecl(*I); 00197 } 00198 return true; 00199 } 00200 void HandleTopLevelSingleDecl(Decl *D); 00201 void HandleDeclInMainFile(Decl *D); 00202 RewriteModernObjC(std::string inFile, raw_ostream *OS, 00203 DiagnosticsEngine &D, const LangOptions &LOpts, 00204 bool silenceMacroWarn); 00205 00206 ~RewriteModernObjC() {} 00207 00208 virtual void HandleTranslationUnit(ASTContext &C); 00209 00210 void ReplaceStmt(Stmt *Old, Stmt *New) { 00211 Stmt *ReplacingStmt = ReplacedNodes[Old]; 00212 00213 if (ReplacingStmt) 00214 return; // We can't rewrite the same node twice. 00215 00216 if (DisableReplaceStmt) 00217 return; 00218 00219 // If replacement succeeded or warning disabled return with no warning. 00220 if (!Rewrite.ReplaceStmt(Old, New)) { 00221 ReplacedNodes[Old] = New; 00222 return; 00223 } 00224 if (SilenceRewriteMacroWarning) 00225 return; 00226 Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 00227 << Old->getSourceRange(); 00228 } 00229 00230 void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { 00231 if (DisableReplaceStmt) 00232 return; 00233 00234 // Measure the old text. 00235 int Size = Rewrite.getRangeSize(SrcRange); 00236 if (Size == -1) { 00237 Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 00238 << Old->getSourceRange(); 00239 return; 00240 } 00241 // Get the new text. 00242 std::string SStr; 00243 llvm::raw_string_ostream S(SStr); 00244 New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts)); 00245 const std::string &Str = S.str(); 00246 00247 // If replacement succeeded or warning disabled return with no warning. 00248 if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) { 00249 ReplacedNodes[Old] = New; 00250 return; 00251 } 00252 if (SilenceRewriteMacroWarning) 00253 return; 00254 Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag) 00255 << Old->getSourceRange(); 00256 } 00257 00258 void InsertText(SourceLocation Loc, StringRef Str, 00259 bool InsertAfter = true) { 00260 // If insertion succeeded or warning disabled return with no warning. 00261 if (!Rewrite.InsertText(Loc, Str, InsertAfter) || 00262 SilenceRewriteMacroWarning) 00263 return; 00264 00265 Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag); 00266 } 00267 00268 void ReplaceText(SourceLocation Start, unsigned OrigLength, 00269 StringRef Str) { 00270 // If removal succeeded or warning disabled return with no warning. 00271 if (!Rewrite.ReplaceText(Start, OrigLength, Str) || 00272 SilenceRewriteMacroWarning) 00273 return; 00274 00275 Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag); 00276 } 00277 00278 // Syntactic Rewriting. 00279 void RewriteRecordBody(RecordDecl *RD); 00280 void RewriteInclude(); 00281 void RewriteForwardClassDecl(DeclGroupRef D); 00282 void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG); 00283 void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 00284 const std::string &typedefString); 00285 void RewriteImplementations(); 00286 void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 00287 ObjCImplementationDecl *IMD, 00288 ObjCCategoryImplDecl *CID); 00289 void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl); 00290 void RewriteImplementationDecl(Decl *Dcl); 00291 void RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 00292 ObjCMethodDecl *MDecl, std::string &ResultStr); 00293 void RewriteTypeIntoString(QualType T, std::string &ResultStr, 00294 const FunctionType *&FPRetType); 00295 void RewriteByRefString(std::string &ResultStr, const std::string &Name, 00296 ValueDecl *VD, bool def=false); 00297 void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); 00298 void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); 00299 void RewriteForwardProtocolDecl(DeclGroupRef D); 00300 void RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG); 00301 void RewriteMethodDeclaration(ObjCMethodDecl *Method); 00302 void RewriteProperty(ObjCPropertyDecl *prop); 00303 void RewriteFunctionDecl(FunctionDecl *FD); 00304 void RewriteBlockPointerType(std::string& Str, QualType Type); 00305 void RewriteBlockPointerTypeVariable(std::string& Str, ValueDecl *VD); 00306 void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); 00307 void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); 00308 void RewriteTypeOfDecl(VarDecl *VD); 00309 void RewriteObjCQualifiedInterfaceTypes(Expr *E); 00310 00311 std::string getIvarAccessString(ObjCIvarDecl *D); 00312 00313 // Expression Rewriting. 00314 Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); 00315 Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); 00316 Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo); 00317 Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo); 00318 Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); 00319 Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); 00320 Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); 00321 Stmt *RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp); 00322 Stmt *RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp); 00323 Stmt *RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp); 00324 Stmt *RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp); 00325 Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); 00326 Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); 00327 Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S); 00328 Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); 00329 Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 00330 SourceLocation OrigEnd); 00331 Stmt *RewriteBreakStmt(BreakStmt *S); 00332 Stmt *RewriteContinueStmt(ContinueStmt *S); 00333 void RewriteCastExpr(CStyleCastExpr *CE); 00334 void RewriteImplicitCastObjCExpr(CastExpr *IE); 00335 void RewriteLinkageSpec(LinkageSpecDecl *LSD); 00336 00337 // Block rewriting. 00338 void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); 00339 00340 // Block specific rewrite rules. 00341 void RewriteBlockPointerDecl(NamedDecl *VD); 00342 void RewriteByRefVar(VarDecl *VD, bool firstDecl, bool lastDecl); 00343 Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD); 00344 Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); 00345 void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); 00346 00347 void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 00348 std::string &Result); 00349 00350 void RewriteObjCFieldDecl(FieldDecl *fieldDecl, std::string &Result); 00351 bool IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, TagDecl *Tag, 00352 bool &IsNamedDefinition); 00353 void RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl, 00354 std::string &Result); 00355 00356 bool RewriteObjCFieldDeclType(QualType &Type, std::string &Result); 00357 00358 void RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, 00359 std::string &Result); 00360 00361 virtual void Initialize(ASTContext &context); 00362 00363 // Misc. AST transformation routines. Somtimes they end up calling 00364 // rewriting routines on the new ASTs. 00365 CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, 00366 Expr **args, unsigned nargs, 00367 SourceLocation StartLoc=SourceLocation(), 00368 SourceLocation EndLoc=SourceLocation()); 00369 00370 Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, 00371 SourceLocation StartLoc=SourceLocation(), 00372 SourceLocation EndLoc=SourceLocation()); 00373 00374 void SynthCountByEnumWithState(std::string &buf); 00375 void SynthMsgSendFunctionDecl(); 00376 void SynthMsgSendSuperFunctionDecl(); 00377 void SynthMsgSendStretFunctionDecl(); 00378 void SynthMsgSendFpretFunctionDecl(); 00379 void SynthMsgSendSuperStretFunctionDecl(); 00380 void SynthGetClassFunctionDecl(); 00381 void SynthGetMetaClassFunctionDecl(); 00382 void SynthGetSuperClassFunctionDecl(); 00383 void SynthSelGetUidFunctionDecl(); 00384 void SynthSuperContructorFunctionDecl(); 00385 00386 // Rewriting metadata 00387 template<typename MethodIterator> 00388 void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 00389 MethodIterator MethodEnd, 00390 bool IsInstanceMethod, 00391 StringRef prefix, 00392 StringRef ClassName, 00393 std::string &Result); 00394 void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, 00395 std::string &Result); 00396 void RewriteObjCProtocolListMetaData( 00397 const ObjCList<ObjCProtocolDecl> &Prots, 00398 StringRef prefix, StringRef ClassName, std::string &Result); 00399 void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 00400 std::string &Result); 00401 void RewriteClassSetupInitHook(std::string &Result); 00402 00403 void RewriteMetaDataIntoBuffer(std::string &Result); 00404 void WriteImageInfo(std::string &Result); 00405 void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, 00406 std::string &Result); 00407 void RewriteCategorySetupInitHook(std::string &Result); 00408 00409 // Rewriting ivar 00410 void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 00411 std::string &Result); 00412 Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV); 00413 00414 00415 std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); 00416 std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 00417 StringRef funcName, std::string Tag); 00418 std::string SynthesizeBlockFunc(BlockExpr *CE, int i, 00419 StringRef funcName, std::string Tag); 00420 std::string SynthesizeBlockImpl(BlockExpr *CE, 00421 std::string Tag, std::string Desc); 00422 std::string SynthesizeBlockDescriptor(std::string DescTag, 00423 std::string ImplTag, 00424 int i, StringRef funcName, 00425 unsigned hasCopy); 00426 Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); 00427 void SynthesizeBlockLiterals(SourceLocation FunLocStart, 00428 StringRef FunName); 00429 FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); 00430 Stmt *SynthBlockInitExpr(BlockExpr *Exp, 00431 const SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs); 00432 00433 // Misc. helper routines. 00434 QualType getProtocolType(); 00435 void WarnAboutReturnGotoStmts(Stmt *S); 00436 void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); 00437 void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); 00438 void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); 00439 00440 bool IsDeclStmtInForeachHeader(DeclStmt *DS); 00441 void CollectBlockDeclRefInfo(BlockExpr *Exp); 00442 void GetBlockDeclRefExprs(Stmt *S); 00443 void GetInnerBlockDeclRefExprs(Stmt *S, 00444 SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs, 00445 llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts); 00446 00447 // We avoid calling Type::isBlockPointerType(), since it operates on the 00448 // canonical type. We only care if the top-level type is a closure pointer. 00449 bool isTopLevelBlockPointerType(QualType T) { 00450 return isa<BlockPointerType>(T); 00451 } 00452 00453 /// convertBlockPointerToFunctionPointer - Converts a block-pointer type 00454 /// to a function pointer type and upon success, returns true; false 00455 /// otherwise. 00456 bool convertBlockPointerToFunctionPointer(QualType &T) { 00457 if (isTopLevelBlockPointerType(T)) { 00458 const BlockPointerType *BPT = T->getAs<BlockPointerType>(); 00459 T = Context->getPointerType(BPT->getPointeeType()); 00460 return true; 00461 } 00462 return false; 00463 } 00464 00465 bool convertObjCTypeToCStyleType(QualType &T); 00466 00467 bool needToScanForQualifiers(QualType T); 00468 QualType getSuperStructType(); 00469 QualType getConstantStringStructType(); 00470 QualType convertFunctionTypeOfBlocks(const FunctionType *FT); 00471 bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); 00472 00473 void convertToUnqualifiedObjCType(QualType &T) { 00474 if (T->isObjCQualifiedIdType()) { 00475 bool isConst = T.isConstQualified(); 00476 T = isConst ? Context->getObjCIdType().withConst() 00477 : Context->getObjCIdType(); 00478 } 00479 else if (T->isObjCQualifiedClassType()) 00480 T = Context->getObjCClassType(); 00481 else if (T->isObjCObjectPointerType() && 00482 T->getPointeeType()->isObjCQualifiedInterfaceType()) { 00483 if (const ObjCObjectPointerType * OBJPT = 00484 T->getAsObjCInterfacePointerType()) { 00485 const ObjCInterfaceType *IFaceT = OBJPT->getInterfaceType(); 00486 T = QualType(IFaceT, 0); 00487 T = Context->getPointerType(T); 00488 } 00489 } 00490 } 00491 00492 // FIXME: This predicate seems like it would be useful to add to ASTContext. 00493 bool isObjCType(QualType T) { 00494 if (!LangOpts.ObjC1 && !LangOpts.ObjC2) 00495 return false; 00496 00497 QualType OCT = Context->getCanonicalType(T).getUnqualifiedType(); 00498 00499 if (OCT == Context->getCanonicalType(Context->getObjCIdType()) || 00500 OCT == Context->getCanonicalType(Context->getObjCClassType())) 00501 return true; 00502 00503 if (const PointerType *PT = OCT->getAs<PointerType>()) { 00504 if (isa<ObjCInterfaceType>(PT->getPointeeType()) || 00505 PT->getPointeeType()->isObjCQualifiedIdType()) 00506 return true; 00507 } 00508 return false; 00509 } 00510 bool PointerTypeTakesAnyBlockArguments(QualType QT); 00511 bool PointerTypeTakesAnyObjCQualifiedType(QualType QT); 00512 void GetExtentOfArgList(const char *Name, const char *&LParen, 00513 const char *&RParen); 00514 00515 void QuoteDoublequotes(std::string &From, std::string &To) { 00516 for (unsigned i = 0; i < From.length(); i++) { 00517 if (From[i] == '"') 00518 To += "\\\""; 00519 else 00520 To += From[i]; 00521 } 00522 } 00523 00524 QualType getSimpleFunctionType(QualType result, 00525 const QualType *args, 00526 unsigned numArgs, 00527 bool variadic = false) { 00528 if (result == Context->getObjCInstanceType()) 00529 result = Context->getObjCIdType(); 00530 FunctionProtoType::ExtProtoInfo fpi; 00531 fpi.Variadic = variadic; 00532 return Context->getFunctionType(result, args, numArgs, fpi); 00533 } 00534 00535 // Helper function: create a CStyleCastExpr with trivial type source info. 00536 CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, 00537 CastKind Kind, Expr *E) { 00538 TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); 00539 return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo, 00540 SourceLocation(), SourceLocation()); 00541 } 00542 00543 bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const { 00544 IdentifierInfo* II = &Context->Idents.get("load"); 00545 Selector LoadSel = Context->Selectors.getSelector(0, &II); 00546 return OD->getClassMethod(LoadSel) != 0; 00547 } 00548 }; 00549 00550 } 00551 00552 void RewriteModernObjC::RewriteBlocksInFunctionProtoType(QualType funcType, 00553 NamedDecl *D) { 00554 if (const FunctionProtoType *fproto 00555 = dyn_cast<FunctionProtoType>(funcType.IgnoreParens())) { 00556 for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(), 00557 E = fproto->arg_type_end(); I && (I != E); ++I) 00558 if (isTopLevelBlockPointerType(*I)) { 00559 // All the args are checked/rewritten. Don't call twice! 00560 RewriteBlockPointerDecl(D); 00561 break; 00562 } 00563 } 00564 } 00565 00566 void RewriteModernObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) { 00567 const PointerType *PT = funcType->getAs<PointerType>(); 00568 if (PT && PointerTypeTakesAnyBlockArguments(funcType)) 00569 RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND); 00570 } 00571 00572 static bool IsHeaderFile(const std::string &Filename) { 00573 std::string::size_type DotPos = Filename.rfind('.'); 00574 00575 if (DotPos == std::string::npos) { 00576 // no file extension 00577 return false; 00578 } 00579 00580 std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end()); 00581 // C header: .h 00582 // C++ header: .hh or .H; 00583 return Ext == "h" || Ext == "hh" || Ext == "H"; 00584 } 00585 00586 RewriteModernObjC::RewriteModernObjC(std::string inFile, raw_ostream* OS, 00587 DiagnosticsEngine &D, const LangOptions &LOpts, 00588 bool silenceMacroWarn) 00589 : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS), 00590 SilenceRewriteMacroWarning(silenceMacroWarn) { 00591 IsHeader = IsHeaderFile(inFile); 00592 RewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 00593 "rewriting sub-expression within a macro (may not be correct)"); 00594 // FIXME. This should be an error. But if block is not called, it is OK. And it 00595 // may break including some headers. 00596 GlobalBlockRewriteFailedDiag = Diags.getCustomDiagID(DiagnosticsEngine::Warning, 00597 "rewriting block literal declared in global scope is not implemented"); 00598 00599 TryFinallyContainsReturnDiag = Diags.getCustomDiagID( 00600 DiagnosticsEngine::Warning, 00601 "rewriter doesn't support user-specified control flow semantics " 00602 "for @try/@finally (code may not execute properly)"); 00603 } 00604 00605 ASTConsumer *clang::CreateModernObjCRewriter(const std::string& InFile, 00606 raw_ostream* OS, 00607 DiagnosticsEngine &Diags, 00608 const LangOptions &LOpts, 00609 bool SilenceRewriteMacroWarning) { 00610 return new RewriteModernObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); 00611 } 00612 00613 void RewriteModernObjC::InitializeCommon(ASTContext &context) { 00614 Context = &context; 00615 SM = &Context->getSourceManager(); 00616 TUDecl = Context->getTranslationUnitDecl(); 00617 MsgSendFunctionDecl = 0; 00618 MsgSendSuperFunctionDecl = 0; 00619 MsgSendStretFunctionDecl = 0; 00620 MsgSendSuperStretFunctionDecl = 0; 00621 MsgSendFpretFunctionDecl = 0; 00622 GetClassFunctionDecl = 0; 00623 GetMetaClassFunctionDecl = 0; 00624 GetSuperClassFunctionDecl = 0; 00625 SelGetUidFunctionDecl = 0; 00626 CFStringFunctionDecl = 0; 00627 ConstantStringClassReference = 0; 00628 NSStringRecord = 0; 00629 CurMethodDef = 0; 00630 CurFunctionDef = 0; 00631 GlobalVarDecl = 0; 00632 GlobalConstructionExp = 0; 00633 SuperStructDecl = 0; 00634 ProtocolTypeDecl = 0; 00635 ConstantStringDecl = 0; 00636 BcLabelCount = 0; 00637 SuperContructorFunctionDecl = 0; 00638 NumObjCStringLiterals = 0; 00639 PropParentMap = 0; 00640 CurrentBody = 0; 00641 DisableReplaceStmt = false; 00642 objc_impl_method = false; 00643 00644 // Get the ID and start/end of the main file. 00645 MainFileID = SM->getMainFileID(); 00646 const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID); 00647 MainFileStart = MainBuf->getBufferStart(); 00648 MainFileEnd = MainBuf->getBufferEnd(); 00649 00650 Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts()); 00651 } 00652 00653 //===----------------------------------------------------------------------===// 00654 // Top Level Driver Code 00655 //===----------------------------------------------------------------------===// 00656 00657 void RewriteModernObjC::HandleTopLevelSingleDecl(Decl *D) { 00658 if (Diags.hasErrorOccurred()) 00659 return; 00660 00661 // Two cases: either the decl could be in the main file, or it could be in a 00662 // #included file. If the former, rewrite it now. If the later, check to see 00663 // if we rewrote the #include/#import. 00664 SourceLocation Loc = D->getLocation(); 00665 Loc = SM->getExpansionLoc(Loc); 00666 00667 // If this is for a builtin, ignore it. 00668 if (Loc.isInvalid()) return; 00669 00670 // Look for built-in declarations that we need to refer during the rewrite. 00671 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 00672 RewriteFunctionDecl(FD); 00673 } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) { 00674 // declared in <Foundation/NSString.h> 00675 if (FVD->getName() == "_NSConstantStringClassReference") { 00676 ConstantStringClassReference = FVD; 00677 return; 00678 } 00679 } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { 00680 RewriteCategoryDecl(CD); 00681 } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { 00682 if (PD->isThisDeclarationADefinition()) 00683 RewriteProtocolDecl(PD); 00684 } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { 00685 // FIXME. This will not work in all situations and leaving it out 00686 // is harmless. 00687 // RewriteLinkageSpec(LSD); 00688 00689 // Recurse into linkage specifications 00690 for (DeclContext::decl_iterator DI = LSD->decls_begin(), 00691 DIEnd = LSD->decls_end(); 00692 DI != DIEnd; ) { 00693 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) { 00694 if (!IFace->isThisDeclarationADefinition()) { 00695 SmallVector<Decl *, 8> DG; 00696 SourceLocation StartLoc = IFace->getLocStart(); 00697 do { 00698 if (isa<ObjCInterfaceDecl>(*DI) && 00699 !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() && 00700 StartLoc == (*DI)->getLocStart()) 00701 DG.push_back(*DI); 00702 else 00703 break; 00704 00705 ++DI; 00706 } while (DI != DIEnd); 00707 RewriteForwardClassDecl(DG); 00708 continue; 00709 } 00710 else { 00711 // Keep track of all interface declarations seen. 00712 ObjCInterfacesSeen.push_back(IFace); 00713 ++DI; 00714 continue; 00715 } 00716 } 00717 00718 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) { 00719 if (!Proto->isThisDeclarationADefinition()) { 00720 SmallVector<Decl *, 8> DG; 00721 SourceLocation StartLoc = Proto->getLocStart(); 00722 do { 00723 if (isa<ObjCProtocolDecl>(*DI) && 00724 !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() && 00725 StartLoc == (*DI)->getLocStart()) 00726 DG.push_back(*DI); 00727 else 00728 break; 00729 00730 ++DI; 00731 } while (DI != DIEnd); 00732 RewriteForwardProtocolDecl(DG); 00733 continue; 00734 } 00735 } 00736 00737 HandleTopLevelSingleDecl(*DI); 00738 ++DI; 00739 } 00740 } 00741 // If we have a decl in the main file, see if we should rewrite it. 00742 if (SM->isFromMainFile(Loc)) 00743 return HandleDeclInMainFile(D); 00744 } 00745 00746 //===----------------------------------------------------------------------===// 00747 // Syntactic (non-AST) Rewriting Code 00748 //===----------------------------------------------------------------------===// 00749 00750 void RewriteModernObjC::RewriteInclude() { 00751 SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID); 00752 StringRef MainBuf = SM->getBufferData(MainFileID); 00753 const char *MainBufStart = MainBuf.begin(); 00754 const char *MainBufEnd = MainBuf.end(); 00755 size_t ImportLen = strlen("import"); 00756 00757 // Loop over the whole file, looking for includes. 00758 for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { 00759 if (*BufPtr == '#') { 00760 if (++BufPtr == MainBufEnd) 00761 return; 00762 while (*BufPtr == ' ' || *BufPtr == '\t') 00763 if (++BufPtr == MainBufEnd) 00764 return; 00765 if (!strncmp(BufPtr, "import", ImportLen)) { 00766 // replace import with include 00767 SourceLocation ImportLoc = 00768 LocStart.getLocWithOffset(BufPtr-MainBufStart); 00769 ReplaceText(ImportLoc, ImportLen, "include"); 00770 BufPtr += ImportLen; 00771 } 00772 } 00773 } 00774 } 00775 00776 static void WriteInternalIvarName(const ObjCInterfaceDecl *IDecl, 00777 ObjCIvarDecl *IvarDecl, std::string &Result) { 00778 Result += "OBJC_IVAR_$_"; 00779 Result += IDecl->getName(); 00780 Result += "$"; 00781 Result += IvarDecl->getName(); 00782 } 00783 00784 std::string 00785 RewriteModernObjC::getIvarAccessString(ObjCIvarDecl *D) { 00786 const ObjCInterfaceDecl *ClassDecl = D->getContainingInterface(); 00787 00788 // Build name of symbol holding ivar offset. 00789 std::string IvarOffsetName; 00790 WriteInternalIvarName(ClassDecl, D, IvarOffsetName); 00791 00792 00793 std::string S = "(*("; 00794 QualType IvarT = D->getType(); 00795 00796 if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) { 00797 RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl(); 00798 RD = RD->getDefinition(); 00799 if (RD && !RD->getDeclName().getAsIdentifierInfo()) { 00800 // decltype(((Foo_IMPL*)0)->bar) * 00801 ObjCContainerDecl *CDecl = 00802 dyn_cast<ObjCContainerDecl>(D->getDeclContext()); 00803 // ivar in class extensions requires special treatment. 00804 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 00805 CDecl = CatDecl->getClassInterface(); 00806 std::string RecName = CDecl->getName(); 00807 RecName += "_IMPL"; 00808 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 00809 SourceLocation(), SourceLocation(), 00810 &Context->Idents.get(RecName.c_str())); 00811 QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD)); 00812 unsigned UnsignedIntSize = 00813 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 00814 Expr *Zero = IntegerLiteral::Create(*Context, 00815 llvm::APInt(UnsignedIntSize, 0), 00816 Context->UnsignedIntTy, SourceLocation()); 00817 Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero); 00818 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 00819 Zero); 00820 FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 00821 SourceLocation(), 00822 &Context->Idents.get(D->getNameAsString()), 00823 IvarT, 0, 00824 /*BitWidth=*/0, /*Mutable=*/true, 00825 /*HasInit=*/false); 00826 MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 00827 FD->getType(), VK_LValue, 00828 OK_Ordinary); 00829 IvarT = Context->getDecltypeType(ME, ME->getType()); 00830 } 00831 } 00832 convertObjCTypeToCStyleType(IvarT); 00833 QualType castT = Context->getPointerType(IvarT); 00834 std::string TypeString(castT.getAsString(Context->getPrintingPolicy())); 00835 S += TypeString; 00836 S += ")"; 00837 00838 // ((char *)self + IVAR_OFFSET_SYMBOL_NAME) 00839 S += "((char *)self + "; 00840 S += IvarOffsetName; 00841 S += "))"; 00842 ReferencedIvars[const_cast<ObjCInterfaceDecl *>(ClassDecl)].insert(D); 00843 return S; 00844 } 00845 00846 /// mustSynthesizeSetterGetterMethod - returns true if setter or getter has not 00847 /// been found in the class implementation. In this case, it must be synthesized. 00848 static bool mustSynthesizeSetterGetterMethod(ObjCImplementationDecl *IMP, 00849 ObjCPropertyDecl *PD, 00850 bool getter) { 00851 return getter ? !IMP->getInstanceMethod(PD->getGetterName()) 00852 : !IMP->getInstanceMethod(PD->getSetterName()); 00853 00854 } 00855 00856 void RewriteModernObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, 00857 ObjCImplementationDecl *IMD, 00858 ObjCCategoryImplDecl *CID) { 00859 static bool objcGetPropertyDefined = false; 00860 static bool objcSetPropertyDefined = false; 00861 SourceLocation startGetterSetterLoc; 00862 00863 if (PID->getLocStart().isValid()) { 00864 SourceLocation startLoc = PID->getLocStart(); 00865 InsertText(startLoc, "// "); 00866 const char *startBuf = SM->getCharacterData(startLoc); 00867 assert((*startBuf == '@') && "bogus @synthesize location"); 00868 const char *semiBuf = strchr(startBuf, ';'); 00869 assert((*semiBuf == ';') && "@synthesize: can't find ';'"); 00870 startGetterSetterLoc = startLoc.getLocWithOffset(semiBuf-startBuf+1); 00871 } 00872 else 00873 startGetterSetterLoc = IMD ? IMD->getLocEnd() : CID->getLocEnd(); 00874 00875 if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 00876 return; // FIXME: is this correct? 00877 00878 // Generate the 'getter' function. 00879 ObjCPropertyDecl *PD = PID->getPropertyDecl(); 00880 ObjCIvarDecl *OID = PID->getPropertyIvarDecl(); 00881 00882 if (!OID) 00883 return; 00884 unsigned Attributes = PD->getPropertyAttributes(); 00885 if (mustSynthesizeSetterGetterMethod(IMD, PD, true /*getter*/)) { 00886 bool GenGetProperty = !(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) && 00887 (Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 00888 ObjCPropertyDecl::OBJC_PR_copy)); 00889 std::string Getr; 00890 if (GenGetProperty && !objcGetPropertyDefined) { 00891 objcGetPropertyDefined = true; 00892 // FIXME. Is this attribute correct in all cases? 00893 Getr = "\nextern \"C\" __declspec(dllimport) " 00894 "id objc_getProperty(id, SEL, long, bool);\n"; 00895 } 00896 RewriteObjCMethodDecl(OID->getContainingInterface(), 00897 PD->getGetterMethodDecl(), Getr); 00898 Getr += "{ "; 00899 // Synthesize an explicit cast to gain access to the ivar. 00900 // See objc-act.c:objc_synthesize_new_getter() for details. 00901 if (GenGetProperty) { 00902 // return objc_getProperty(self, _cmd, offsetof(ClassDecl, OID), 1) 00903 Getr += "typedef "; 00904 const FunctionType *FPRetType = 0; 00905 RewriteTypeIntoString(PD->getGetterMethodDecl()->getResultType(), Getr, 00906 FPRetType); 00907 Getr += " _TYPE"; 00908 if (FPRetType) { 00909 Getr += ")"; // close the precedence "scope" for "*". 00910 00911 // Now, emit the argument types (if any). 00912 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)){ 00913 Getr += "("; 00914 for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 00915 if (i) Getr += ", "; 00916 std::string ParamStr = FT->getArgType(i).getAsString( 00917 Context->getPrintingPolicy()); 00918 Getr += ParamStr; 00919 } 00920 if (FT->isVariadic()) { 00921 if (FT->getNumArgs()) Getr += ", "; 00922 Getr += "..."; 00923 } 00924 Getr += ")"; 00925 } else 00926 Getr += "()"; 00927 } 00928 Getr += ";\n"; 00929 Getr += "return (_TYPE)"; 00930 Getr += "objc_getProperty(self, _cmd, "; 00931 RewriteIvarOffsetComputation(OID, Getr); 00932 Getr += ", 1)"; 00933 } 00934 else 00935 Getr += "return " + getIvarAccessString(OID); 00936 Getr += "; }"; 00937 InsertText(startGetterSetterLoc, Getr); 00938 } 00939 00940 if (PD->isReadOnly() || 00941 !mustSynthesizeSetterGetterMethod(IMD, PD, false /*setter*/)) 00942 return; 00943 00944 // Generate the 'setter' function. 00945 std::string Setr; 00946 bool GenSetProperty = Attributes & (ObjCPropertyDecl::OBJC_PR_retain | 00947 ObjCPropertyDecl::OBJC_PR_copy); 00948 if (GenSetProperty && !objcSetPropertyDefined) { 00949 objcSetPropertyDefined = true; 00950 // FIXME. Is this attribute correct in all cases? 00951 Setr = "\nextern \"C\" __declspec(dllimport) " 00952 "void objc_setProperty (id, SEL, long, id, bool, bool);\n"; 00953 } 00954 00955 RewriteObjCMethodDecl(OID->getContainingInterface(), 00956 PD->getSetterMethodDecl(), Setr); 00957 Setr += "{ "; 00958 // Synthesize an explicit cast to initialize the ivar. 00959 // See objc-act.c:objc_synthesize_new_setter() for details. 00960 if (GenSetProperty) { 00961 Setr += "objc_setProperty (self, _cmd, "; 00962 RewriteIvarOffsetComputation(OID, Setr); 00963 Setr += ", (id)"; 00964 Setr += PD->getName(); 00965 Setr += ", "; 00966 if (Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) 00967 Setr += "0, "; 00968 else 00969 Setr += "1, "; 00970 if (Attributes & ObjCPropertyDecl::OBJC_PR_copy) 00971 Setr += "1)"; 00972 else 00973 Setr += "0)"; 00974 } 00975 else { 00976 Setr += getIvarAccessString(OID) + " = "; 00977 Setr += PD->getName(); 00978 } 00979 Setr += "; }\n"; 00980 InsertText(startGetterSetterLoc, Setr); 00981 } 00982 00983 static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, 00984 std::string &typedefString) { 00985 typedefString += "#ifndef _REWRITER_typedef_"; 00986 typedefString += ForwardDecl->getNameAsString(); 00987 typedefString += "\n"; 00988 typedefString += "#define _REWRITER_typedef_"; 00989 typedefString += ForwardDecl->getNameAsString(); 00990 typedefString += "\n"; 00991 typedefString += "typedef struct objc_object "; 00992 typedefString += ForwardDecl->getNameAsString(); 00993 // typedef struct { } _objc_exc_Classname; 00994 typedefString += ";\ntypedef struct {} _objc_exc_"; 00995 typedefString += ForwardDecl->getNameAsString(); 00996 typedefString += ";\n#endif\n"; 00997 } 00998 00999 void RewriteModernObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, 01000 const std::string &typedefString) { 01001 SourceLocation startLoc = ClassDecl->getLocStart(); 01002 const char *startBuf = SM->getCharacterData(startLoc); 01003 const char *semiPtr = strchr(startBuf, ';'); 01004 // Replace the @class with typedefs corresponding to the classes. 01005 ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); 01006 } 01007 01008 void RewriteModernObjC::RewriteForwardClassDecl(DeclGroupRef D) { 01009 std::string typedefString; 01010 for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { 01011 ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I); 01012 if (I == D.begin()) { 01013 // Translate to typedef's that forward reference structs with the same name 01014 // as the class. As a convenience, we include the original declaration 01015 // as a comment. 01016 typedefString += "// @class "; 01017 typedefString += ForwardDecl->getNameAsString(); 01018 typedefString += ";\n"; 01019 } 01020 RewriteOneForwardClassDecl(ForwardDecl, typedefString); 01021 } 01022 DeclGroupRef::iterator I = D.begin(); 01023 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString); 01024 } 01025 01026 void RewriteModernObjC::RewriteForwardClassDecl( 01027 const llvm::SmallVector<Decl*, 8> &D) { 01028 std::string typedefString; 01029 for (unsigned i = 0; i < D.size(); i++) { 01030 ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]); 01031 if (i == 0) { 01032 typedefString += "// @class "; 01033 typedefString += ForwardDecl->getNameAsString(); 01034 typedefString += ";\n"; 01035 } 01036 RewriteOneForwardClassDecl(ForwardDecl, typedefString); 01037 } 01038 RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString); 01039 } 01040 01041 void RewriteModernObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { 01042 // When method is a synthesized one, such as a getter/setter there is 01043 // nothing to rewrite. 01044 if (Method->isImplicit()) 01045 return; 01046 SourceLocation LocStart = Method->getLocStart(); 01047 SourceLocation LocEnd = Method->getLocEnd(); 01048 01049 if (SM->getExpansionLineNumber(LocEnd) > 01050 SM->getExpansionLineNumber(LocStart)) { 01051 InsertText(LocStart, "#if 0\n"); 01052 ReplaceText(LocEnd, 1, ";\n#endif\n"); 01053 } else { 01054 InsertText(LocStart, "// "); 01055 } 01056 } 01057 01058 void RewriteModernObjC::RewriteProperty(ObjCPropertyDecl *prop) { 01059 SourceLocation Loc = prop->getAtLoc(); 01060 01061 ReplaceText(Loc, 0, "// "); 01062 // FIXME: handle properties that are declared across multiple lines. 01063 } 01064 01065 void RewriteModernObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { 01066 SourceLocation LocStart = CatDecl->getLocStart(); 01067 01068 // FIXME: handle category headers that are declared across multiple lines. 01069 if (CatDecl->getIvarRBraceLoc().isValid()) { 01070 ReplaceText(LocStart, 1, "/** "); 01071 ReplaceText(CatDecl->getIvarRBraceLoc(), 1, "**/ "); 01072 } 01073 else { 01074 ReplaceText(LocStart, 0, "// "); 01075 } 01076 01077 for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), 01078 E = CatDecl->prop_end(); I != E; ++I) 01079 RewriteProperty(&*I); 01080 01081 for (ObjCCategoryDecl::instmeth_iterator 01082 I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); 01083 I != E; ++I) 01084 RewriteMethodDeclaration(*I); 01085 for (ObjCCategoryDecl::classmeth_iterator 01086 I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); 01087 I != E; ++I) 01088 RewriteMethodDeclaration(*I); 01089 01090 // Lastly, comment out the @end. 01091 ReplaceText(CatDecl->getAtEndRange().getBegin(), 01092 strlen("@end"), "/* @end */"); 01093 } 01094 01095 void RewriteModernObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { 01096 SourceLocation LocStart = PDecl->getLocStart(); 01097 assert(PDecl->isThisDeclarationADefinition()); 01098 01099 // FIXME: handle protocol headers that are declared across multiple lines. 01100 ReplaceText(LocStart, 0, "// "); 01101 01102 for (ObjCProtocolDecl::instmeth_iterator 01103 I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 01104 I != E; ++I) 01105 RewriteMethodDeclaration(*I); 01106 for (ObjCProtocolDecl::classmeth_iterator 01107 I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 01108 I != E; ++I) 01109 RewriteMethodDeclaration(*I); 01110 01111 for (ObjCInterfaceDecl::prop_iterator I = PDecl->prop_begin(), 01112 E = PDecl->prop_end(); I != E; ++I) 01113 RewriteProperty(&*I); 01114 01115 // Lastly, comment out the @end. 01116 SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); 01117 ReplaceText(LocEnd, strlen("@end"), "/* @end */"); 01118 01119 // Must comment out @optional/@required 01120 const char *startBuf = SM->getCharacterData(LocStart); 01121 const char *endBuf = SM->getCharacterData(LocEnd); 01122 for (const char *p = startBuf; p < endBuf; p++) { 01123 if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { 01124 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 01125 ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); 01126 01127 } 01128 else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { 01129 SourceLocation OptionalLoc = LocStart.getLocWithOffset(p-startBuf); 01130 ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); 01131 01132 } 01133 } 01134 } 01135 01136 void RewriteModernObjC::RewriteForwardProtocolDecl(DeclGroupRef D) { 01137 SourceLocation LocStart = (*D.begin())->getLocStart(); 01138 if (LocStart.isInvalid()) 01139 llvm_unreachable("Invalid SourceLocation"); 01140 // FIXME: handle forward protocol that are declared across multiple lines. 01141 ReplaceText(LocStart, 0, "// "); 01142 } 01143 01144 void 01145 RewriteModernObjC::RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG) { 01146 SourceLocation LocStart = DG[0]->getLocStart(); 01147 if (LocStart.isInvalid()) 01148 llvm_unreachable("Invalid SourceLocation"); 01149 // FIXME: handle forward protocol that are declared across multiple lines. 01150 ReplaceText(LocStart, 0, "// "); 01151 } 01152 01153 void 01154 RewriteModernObjC::RewriteLinkageSpec(LinkageSpecDecl *LSD) { 01155 SourceLocation LocStart = LSD->getExternLoc(); 01156 if (LocStart.isInvalid()) 01157 llvm_unreachable("Invalid extern SourceLocation"); 01158 01159 ReplaceText(LocStart, 0, "// "); 01160 if (!LSD->hasBraces()) 01161 return; 01162 // FIXME. We don't rewrite well if '{' is not on same line as 'extern'. 01163 SourceLocation LocRBrace = LSD->getRBraceLoc(); 01164 if (LocRBrace.isInvalid()) 01165 llvm_unreachable("Invalid rbrace SourceLocation"); 01166 ReplaceText(LocRBrace, 0, "// "); 01167 } 01168 01169 void RewriteModernObjC::RewriteTypeIntoString(QualType T, std::string &ResultStr, 01170 const FunctionType *&FPRetType) { 01171 if (T->isObjCQualifiedIdType()) 01172 ResultStr += "id"; 01173 else if (T->isFunctionPointerType() || 01174 T->isBlockPointerType()) { 01175 // needs special handling, since pointer-to-functions have special 01176 // syntax (where a decaration models use). 01177 QualType retType = T; 01178 QualType PointeeTy; 01179 if (const PointerType* PT = retType->getAs<PointerType>()) 01180 PointeeTy = PT->getPointeeType(); 01181 else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>()) 01182 PointeeTy = BPT->getPointeeType(); 01183 if ((FPRetType = PointeeTy->getAs<FunctionType>())) { 01184 ResultStr += FPRetType->getResultType().getAsString( 01185 Context->getPrintingPolicy()); 01186 ResultStr += "(*"; 01187 } 01188 } else 01189 ResultStr += T.getAsString(Context->getPrintingPolicy()); 01190 } 01191 01192 void RewriteModernObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, 01193 ObjCMethodDecl *OMD, 01194 std::string &ResultStr) { 01195 //fprintf(stderr,"In RewriteObjCMethodDecl\n"); 01196 const FunctionType *FPRetType = 0; 01197 ResultStr += "\nstatic "; 01198 RewriteTypeIntoString(OMD->getResultType(), ResultStr, FPRetType); 01199 ResultStr += " "; 01200 01201 // Unique method name 01202 std::string NameStr; 01203 01204 if (OMD->isInstanceMethod()) 01205 NameStr += "_I_"; 01206 else 01207 NameStr += "_C_"; 01208 01209 NameStr += IDecl->getNameAsString(); 01210 NameStr += "_"; 01211 01212 if (ObjCCategoryImplDecl *CID = 01213 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 01214 NameStr += CID->getNameAsString(); 01215 NameStr += "_"; 01216 } 01217 // Append selector names, replacing ':' with '_' 01218 { 01219 std::string selString = OMD->getSelector().getAsString(); 01220 int len = selString.size(); 01221 for (int i = 0; i < len; i++) 01222 if (selString[i] == ':') 01223 selString[i] = '_'; 01224 NameStr += selString; 01225 } 01226 // Remember this name for metadata emission 01227 MethodInternalNames[OMD] = NameStr; 01228 ResultStr += NameStr; 01229 01230 // Rewrite arguments 01231 ResultStr += "("; 01232 01233 // invisible arguments 01234 if (OMD->isInstanceMethod()) { 01235 QualType selfTy = Context->getObjCInterfaceType(IDecl); 01236 selfTy = Context->getPointerType(selfTy); 01237 if (!LangOpts.MicrosoftExt) { 01238 if (ObjCSynthesizedStructs.count(const_cast<ObjCInterfaceDecl*>(IDecl))) 01239 ResultStr += "struct "; 01240 } 01241 // When rewriting for Microsoft, explicitly omit the structure name. 01242 ResultStr += IDecl->getNameAsString(); 01243 ResultStr += " *"; 01244 } 01245 else 01246 ResultStr += Context->getObjCClassType().getAsString( 01247 Context->getPrintingPolicy()); 01248 01249 ResultStr += " self, "; 01250 ResultStr += Context->getObjCSelType().getAsString(Context->getPrintingPolicy()); 01251 ResultStr += " _cmd"; 01252 01253 // Method arguments. 01254 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 01255 E = OMD->param_end(); PI != E; ++PI) { 01256 ParmVarDecl *PDecl = *PI; 01257 ResultStr += ", "; 01258 if (PDecl->getType()->isObjCQualifiedIdType()) { 01259 ResultStr += "id "; 01260 ResultStr += PDecl->getNameAsString(); 01261 } else { 01262 std::string Name = PDecl->getNameAsString(); 01263 QualType QT = PDecl->getType(); 01264 // Make sure we convert "t (^)(...)" to "t (*)(...)". 01265 (void)convertBlockPointerToFunctionPointer(QT); 01266 QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 01267 ResultStr += Name; 01268 } 01269 } 01270 if (OMD->isVariadic()) 01271 ResultStr += ", ..."; 01272 ResultStr += ") "; 01273 01274 if (FPRetType) { 01275 ResultStr += ")"; // close the precedence "scope" for "*". 01276 01277 // Now, emit the argument types (if any). 01278 if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) { 01279 ResultStr += "("; 01280 for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) { 01281 if (i) ResultStr += ", "; 01282 std::string ParamStr = FT->getArgType(i).getAsString( 01283 Context->getPrintingPolicy()); 01284 ResultStr += ParamStr; 01285 } 01286 if (FT->isVariadic()) { 01287 if (FT->getNumArgs()) ResultStr += ", "; 01288 ResultStr += "..."; 01289 } 01290 ResultStr += ")"; 01291 } else { 01292 ResultStr += "()"; 01293 } 01294 } 01295 } 01296 void RewriteModernObjC::RewriteImplementationDecl(Decl *OID) { 01297 ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); 01298 ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); 01299 01300 if (IMD) { 01301 if (IMD->getIvarRBraceLoc().isValid()) { 01302 ReplaceText(IMD->getLocStart(), 1, "/** "); 01303 ReplaceText(IMD->getIvarRBraceLoc(), 1, "**/ "); 01304 } 01305 else { 01306 InsertText(IMD->getLocStart(), "// "); 01307 } 01308 } 01309 else 01310 InsertText(CID->getLocStart(), "// "); 01311 01312 for (ObjCCategoryImplDecl::instmeth_iterator 01313 I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), 01314 E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); 01315 I != E; ++I) { 01316 std::string ResultStr; 01317 ObjCMethodDecl *OMD = *I; 01318 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 01319 SourceLocation LocStart = OMD->getLocStart(); 01320 SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 01321 01322 const char *startBuf = SM->getCharacterData(LocStart); 01323 const char *endBuf = SM->getCharacterData(LocEnd); 01324 ReplaceText(LocStart, endBuf-startBuf, ResultStr); 01325 } 01326 01327 for (ObjCCategoryImplDecl::classmeth_iterator 01328 I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), 01329 E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); 01330 I != E; ++I) { 01331 std::string ResultStr; 01332 ObjCMethodDecl *OMD = *I; 01333 RewriteObjCMethodDecl(OMD->getClassInterface(), OMD, ResultStr); 01334 SourceLocation LocStart = OMD->getLocStart(); 01335 SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); 01336 01337 const char *startBuf = SM->getCharacterData(LocStart); 01338 const char *endBuf = SM->getCharacterData(LocEnd); 01339 ReplaceText(LocStart, endBuf-startBuf, ResultStr); 01340 } 01341 for (ObjCCategoryImplDecl::propimpl_iterator 01342 I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), 01343 E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); 01344 I != E; ++I) { 01345 RewritePropertyImplDecl(&*I, IMD, CID); 01346 } 01347 01348 InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// "); 01349 } 01350 01351 void RewriteModernObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { 01352 // Do not synthesize more than once. 01353 if (ObjCSynthesizedStructs.count(ClassDecl)) 01354 return; 01355 // Make sure super class's are written before current class is written. 01356 ObjCInterfaceDecl *SuperClass = ClassDecl->getSuperClass(); 01357 while (SuperClass) { 01358 RewriteInterfaceDecl(SuperClass); 01359 SuperClass = SuperClass->getSuperClass(); 01360 } 01361 std::string ResultStr; 01362 if (!ObjCWrittenInterfaces.count(ClassDecl->getCanonicalDecl())) { 01363 // we haven't seen a forward decl - generate a typedef. 01364 RewriteOneForwardClassDecl(ClassDecl, ResultStr); 01365 RewriteIvarOffsetSymbols(ClassDecl, ResultStr); 01366 01367 RewriteObjCInternalStruct(ClassDecl, ResultStr); 01368 // Mark this typedef as having been written into its c++ equivalent. 01369 ObjCWrittenInterfaces.insert(ClassDecl->getCanonicalDecl()); 01370 01371 for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), 01372 E = ClassDecl->prop_end(); I != E; ++I) 01373 RewriteProperty(&*I); 01374 for (ObjCInterfaceDecl::instmeth_iterator 01375 I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); 01376 I != E; ++I) 01377 RewriteMethodDeclaration(*I); 01378 for (ObjCInterfaceDecl::classmeth_iterator 01379 I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); 01380 I != E; ++I) 01381 RewriteMethodDeclaration(*I); 01382 01383 // Lastly, comment out the @end. 01384 ReplaceText(ClassDecl->getAtEndRange().getBegin(), strlen("@end"), 01385 "/* @end */"); 01386 } 01387 } 01388 01389 Stmt *RewriteModernObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) { 01390 SourceRange OldRange = PseudoOp->getSourceRange(); 01391 01392 // We just magically know some things about the structure of this 01393 // expression. 01394 ObjCMessageExpr *OldMsg = 01395 cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr( 01396 PseudoOp->getNumSemanticExprs() - 1)); 01397 01398 // Because the rewriter doesn't allow us to rewrite rewritten code, 01399 // we need to suppress rewriting the sub-statements. 01400 Expr *Base; 01401 SmallVector<Expr*, 2> Args; 01402 { 01403 DisableReplaceStmtScope S(*this); 01404 01405 // Rebuild the base expression if we have one. 01406 Base = 0; 01407 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 01408 Base = OldMsg->getInstanceReceiver(); 01409 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 01410 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 01411 } 01412 01413 unsigned numArgs = OldMsg->getNumArgs(); 01414 for (unsigned i = 0; i < numArgs; i++) { 01415 Expr *Arg = OldMsg->getArg(i); 01416 if (isa<OpaqueValueExpr>(Arg)) 01417 Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr(); 01418 Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg)); 01419 Args.push_back(Arg); 01420 } 01421 } 01422 01423 // TODO: avoid this copy. 01424 SmallVector<SourceLocation, 1> SelLocs; 01425 OldMsg->getSelectorLocs(SelLocs); 01426 01427 ObjCMessageExpr *NewMsg = 0; 01428 switch (OldMsg->getReceiverKind()) { 01429 case ObjCMessageExpr::Class: 01430 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 01431 OldMsg->getValueKind(), 01432 OldMsg->getLeftLoc(), 01433 OldMsg->getClassReceiverTypeInfo(), 01434 OldMsg->getSelector(), 01435 SelLocs, 01436 OldMsg->getMethodDecl(), 01437 Args, 01438 OldMsg->getRightLoc(), 01439 OldMsg->isImplicit()); 01440 break; 01441 01442 case ObjCMessageExpr::Instance: 01443 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 01444 OldMsg->getValueKind(), 01445 OldMsg->getLeftLoc(), 01446 Base, 01447 OldMsg->getSelector(), 01448 SelLocs, 01449 OldMsg->getMethodDecl(), 01450 Args, 01451 OldMsg->getRightLoc(), 01452 OldMsg->isImplicit()); 01453 break; 01454 01455 case ObjCMessageExpr::SuperClass: 01456 case ObjCMessageExpr::SuperInstance: 01457 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 01458 OldMsg->getValueKind(), 01459 OldMsg->getLeftLoc(), 01460 OldMsg->getSuperLoc(), 01461 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 01462 OldMsg->getSuperType(), 01463 OldMsg->getSelector(), 01464 SelLocs, 01465 OldMsg->getMethodDecl(), 01466 Args, 01467 OldMsg->getRightLoc(), 01468 OldMsg->isImplicit()); 01469 break; 01470 } 01471 01472 Stmt *Replacement = SynthMessageExpr(NewMsg); 01473 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 01474 return Replacement; 01475 } 01476 01477 Stmt *RewriteModernObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) { 01478 SourceRange OldRange = PseudoOp->getSourceRange(); 01479 01480 // We just magically know some things about the structure of this 01481 // expression. 01482 ObjCMessageExpr *OldMsg = 01483 cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit()); 01484 01485 // Because the rewriter doesn't allow us to rewrite rewritten code, 01486 // we need to suppress rewriting the sub-statements. 01487 Expr *Base = 0; 01488 SmallVector<Expr*, 1> Args; 01489 { 01490 DisableReplaceStmtScope S(*this); 01491 // Rebuild the base expression if we have one. 01492 if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { 01493 Base = OldMsg->getInstanceReceiver(); 01494 Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); 01495 Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); 01496 } 01497 unsigned numArgs = OldMsg->getNumArgs(); 01498 for (unsigned i = 0; i < numArgs; i++) { 01499 Expr *Arg = OldMsg->getArg(i); 01500 if (isa<OpaqueValueExpr>(Arg)) 01501 Arg = cast<OpaqueValueExpr>(Arg)->getSourceExpr(); 01502 Arg = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Arg)); 01503 Args.push_back(Arg); 01504 } 01505 } 01506 01507 // Intentionally empty. 01508 SmallVector<SourceLocation, 1> SelLocs; 01509 01510 ObjCMessageExpr *NewMsg = 0; 01511 switch (OldMsg->getReceiverKind()) { 01512 case ObjCMessageExpr::Class: 01513 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 01514 OldMsg->getValueKind(), 01515 OldMsg->getLeftLoc(), 01516 OldMsg->getClassReceiverTypeInfo(), 01517 OldMsg->getSelector(), 01518 SelLocs, 01519 OldMsg->getMethodDecl(), 01520 Args, 01521 OldMsg->getRightLoc(), 01522 OldMsg->isImplicit()); 01523 break; 01524 01525 case ObjCMessageExpr::Instance: 01526 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 01527 OldMsg->getValueKind(), 01528 OldMsg->getLeftLoc(), 01529 Base, 01530 OldMsg->getSelector(), 01531 SelLocs, 01532 OldMsg->getMethodDecl(), 01533 Args, 01534 OldMsg->getRightLoc(), 01535 OldMsg->isImplicit()); 01536 break; 01537 01538 case ObjCMessageExpr::SuperClass: 01539 case ObjCMessageExpr::SuperInstance: 01540 NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), 01541 OldMsg->getValueKind(), 01542 OldMsg->getLeftLoc(), 01543 OldMsg->getSuperLoc(), 01544 OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, 01545 OldMsg->getSuperType(), 01546 OldMsg->getSelector(), 01547 SelLocs, 01548 OldMsg->getMethodDecl(), 01549 Args, 01550 OldMsg->getRightLoc(), 01551 OldMsg->isImplicit()); 01552 break; 01553 } 01554 01555 Stmt *Replacement = SynthMessageExpr(NewMsg); 01556 ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); 01557 return Replacement; 01558 } 01559 01560 /// SynthCountByEnumWithState - To print: 01561 /// ((unsigned int (*) 01562 /// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 01563 /// (void *)objc_msgSend)((id)l_collection, 01564 /// sel_registerName( 01565 /// "countByEnumeratingWithState:objects:count:"), 01566 /// &enumState, 01567 /// (id *)__rw_items, (unsigned int)16) 01568 /// 01569 void RewriteModernObjC::SynthCountByEnumWithState(std::string &buf) { 01570 buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " 01571 "id *, unsigned int))(void *)objc_msgSend)"; 01572 buf += "\n\t\t"; 01573 buf += "((id)l_collection,\n\t\t"; 01574 buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; 01575 buf += "\n\t\t"; 01576 buf += "&enumState, " 01577 "(id *)__rw_items, (unsigned int)16)"; 01578 } 01579 01580 /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach 01581 /// statement to exit to its outer synthesized loop. 01582 /// 01583 Stmt *RewriteModernObjC::RewriteBreakStmt(BreakStmt *S) { 01584 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 01585 return S; 01586 // replace break with goto __break_label 01587 std::string buf; 01588 01589 SourceLocation startLoc = S->getLocStart(); 01590 buf = "goto __break_label_"; 01591 buf += utostr(ObjCBcLabelNo.back()); 01592 ReplaceText(startLoc, strlen("break"), buf); 01593 01594 return 0; 01595 } 01596 01597 /// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach 01598 /// statement to continue with its inner synthesized loop. 01599 /// 01600 Stmt *RewriteModernObjC::RewriteContinueStmt(ContinueStmt *S) { 01601 if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back())) 01602 return S; 01603 // replace continue with goto __continue_label 01604 std::string buf; 01605 01606 SourceLocation startLoc = S->getLocStart(); 01607 buf = "goto __continue_label_"; 01608 buf += utostr(ObjCBcLabelNo.back()); 01609 ReplaceText(startLoc, strlen("continue"), buf); 01610 01611 return 0; 01612 } 01613 01614 /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement. 01615 /// It rewrites: 01616 /// for ( type elem in collection) { stmts; } 01617 01618 /// Into: 01619 /// { 01620 /// type elem; 01621 /// struct __objcFastEnumerationState enumState = { 0 }; 01622 /// id __rw_items[16]; 01623 /// id l_collection = (id)collection; 01624 /// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 01625 /// objects:__rw_items count:16]; 01626 /// if (limit) { 01627 /// unsigned long startMutations = *enumState.mutationsPtr; 01628 /// do { 01629 /// unsigned long counter = 0; 01630 /// do { 01631 /// if (startMutations != *enumState.mutationsPtr) 01632 /// objc_enumerationMutation(l_collection); 01633 /// elem = (type)enumState.itemsPtr[counter++]; 01634 /// stmts; 01635 /// __continue_label: ; 01636 /// } while (counter < limit); 01637 /// } while (limit = [l_collection countByEnumeratingWithState:&enumState 01638 /// objects:__rw_items count:16]); 01639 /// elem = nil; 01640 /// __break_label: ; 01641 /// } 01642 /// else 01643 /// elem = nil; 01644 /// } 01645 /// 01646 Stmt *RewriteModernObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, 01647 SourceLocation OrigEnd) { 01648 assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty"); 01649 assert(isa<ObjCForCollectionStmt>(Stmts.back()) && 01650 "ObjCForCollectionStmt Statement stack mismatch"); 01651 assert(!ObjCBcLabelNo.empty() && 01652 "ObjCForCollectionStmt - Label No stack empty"); 01653 01654 SourceLocation startLoc = S->getLocStart(); 01655 const char *startBuf = SM->getCharacterData(startLoc); 01656 StringRef elementName; 01657 std::string elementTypeAsString; 01658 std::string buf; 01659 buf = "\n{\n\t"; 01660 if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) { 01661 // type elem; 01662 NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl()); 01663 QualType ElementType = cast<ValueDecl>(D)->getType(); 01664 if (ElementType->isObjCQualifiedIdType() || 01665 ElementType->isObjCQualifiedInterfaceType()) 01666 // Simply use 'id' for all qualified types. 01667 elementTypeAsString = "id"; 01668 else 01669 elementTypeAsString = ElementType.getAsString(Context->getPrintingPolicy()); 01670 buf += elementTypeAsString; 01671 buf += " "; 01672 elementName = D->getName(); 01673 buf += elementName; 01674 buf += ";\n\t"; 01675 } 01676 else { 01677 DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement()); 01678 elementName = DR->getDecl()->getName(); 01679 ValueDecl *VD = cast<ValueDecl>(DR->getDecl()); 01680 if (VD->getType()->isObjCQualifiedIdType() || 01681 VD->getType()->isObjCQualifiedInterfaceType()) 01682 // Simply use 'id' for all qualified types. 01683 elementTypeAsString = "id"; 01684 else 01685 elementTypeAsString = VD->getType().getAsString(Context->getPrintingPolicy()); 01686 } 01687 01688 // struct __objcFastEnumerationState enumState = { 0 }; 01689 buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; 01690 // id __rw_items[16]; 01691 buf += "id __rw_items[16];\n\t"; 01692 // id l_collection = (id) 01693 buf += "id l_collection = (id)"; 01694 // Find start location of 'collection' the hard way! 01695 const char *startCollectionBuf = startBuf; 01696 startCollectionBuf += 3; // skip 'for' 01697 startCollectionBuf = strchr(startCollectionBuf, '('); 01698 startCollectionBuf++; // skip '(' 01699 // find 'in' and skip it. 01700 while (*startCollectionBuf != ' ' || 01701 *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' || 01702 (*(startCollectionBuf+3) != ' ' && 01703 *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '(')) 01704 startCollectionBuf++; 01705 startCollectionBuf += 3; 01706 01707 // Replace: "for (type element in" with string constructed thus far. 01708 ReplaceText(startLoc, startCollectionBuf - startBuf, buf); 01709 // Replace ')' in for '(' type elem in collection ')' with ';' 01710 SourceLocation rightParenLoc = S->getRParenLoc(); 01711 const char *rparenBuf = SM->getCharacterData(rightParenLoc); 01712 SourceLocation lparenLoc = startLoc.getLocWithOffset(rparenBuf-startBuf); 01713 buf = ";\n\t"; 01714 01715 // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState 01716 // objects:__rw_items count:16]; 01717 // which is synthesized into: 01718 // unsigned int limit = 01719 // ((unsigned int (*) 01720 // (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) 01721 // (void *)objc_msgSend)((id)l_collection, 01722 // sel_registerName( 01723 // "countByEnumeratingWithState:objects:count:"), 01724 // (struct __objcFastEnumerationState *)&state, 01725 // (id *)__rw_items, (unsigned int)16); 01726 buf += "unsigned long limit =\n\t\t"; 01727 SynthCountByEnumWithState(buf); 01728 buf += ";\n\t"; 01729 /// if (limit) { 01730 /// unsigned long startMutations = *enumState.mutationsPtr; 01731 /// do { 01732 /// unsigned long counter = 0; 01733 /// do { 01734 /// if (startMutations != *enumState.mutationsPtr) 01735 /// objc_enumerationMutation(l_collection); 01736 /// elem = (type)enumState.itemsPtr[counter++]; 01737 buf += "if (limit) {\n\t"; 01738 buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t"; 01739 buf += "do {\n\t\t"; 01740 buf += "unsigned long counter = 0;\n\t\t"; 01741 buf += "do {\n\t\t\t"; 01742 buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t"; 01743 buf += "objc_enumerationMutation(l_collection);\n\t\t\t"; 01744 buf += elementName; 01745 buf += " = ("; 01746 buf += elementTypeAsString; 01747 buf += ")enumState.itemsPtr[counter++];"; 01748 // Replace ')' in for '(' type elem in collection ')' with all of these. 01749 ReplaceText(lparenLoc, 1, buf); 01750 01751 /// __continue_label: ; 01752 /// } while (counter < limit); 01753 /// } while (limit = [l_collection countByEnumeratingWithState:&enumState 01754 /// objects:__rw_items count:16]); 01755 /// elem = nil; 01756 /// __break_label: ; 01757 /// } 01758 /// else 01759 /// elem = nil; 01760 /// } 01761 /// 01762 buf = ";\n\t"; 01763 buf += "__continue_label_"; 01764 buf += utostr(ObjCBcLabelNo.back()); 01765 buf += ": ;"; 01766 buf += "\n\t\t"; 01767 buf += "} while (counter < limit);\n\t"; 01768 buf += "} while (limit = "; 01769 SynthCountByEnumWithState(buf); 01770 buf += ");\n\t"; 01771 buf += elementName; 01772 buf += " = (("; 01773 buf += elementTypeAsString; 01774 buf += ")0);\n\t"; 01775 buf += "__break_label_"; 01776 buf += utostr(ObjCBcLabelNo.back()); 01777 buf += ": ;\n\t"; 01778 buf += "}\n\t"; 01779 buf += "else\n\t\t"; 01780 buf += elementName; 01781 buf += " = (("; 01782 buf += elementTypeAsString; 01783 buf += ")0);\n\t"; 01784 buf += "}\n"; 01785 01786 // Insert all these *after* the statement body. 01787 // FIXME: If this should support Obj-C++, support CXXTryStmt 01788 if (isa<CompoundStmt>(S->getBody())) { 01789 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(1); 01790 InsertText(endBodyLoc, buf); 01791 } else { 01792 /* Need to treat single statements specially. For example: 01793 * 01794 * for (A *a in b) if (stuff()) break; 01795 * for (A *a in b) xxxyy; 01796 * 01797 * The following code simply scans ahead to the semi to find the actual end. 01798 */ 01799 const char *stmtBuf = SM->getCharacterData(OrigEnd); 01800 const char *semiBuf = strchr(stmtBuf, ';'); 01801 assert(semiBuf && "Can't find ';'"); 01802 SourceLocation endBodyLoc = OrigEnd.getLocWithOffset(semiBuf-stmtBuf+1); 01803 InsertText(endBodyLoc, buf); 01804 } 01805 Stmts.pop_back(); 01806 ObjCBcLabelNo.pop_back(); 01807 return 0; 01808 } 01809 01810 static void Write_RethrowObject(std::string &buf) { 01811 buf += "{ struct _FIN { _FIN(id reth) : rethrow(reth) {}\n"; 01812 buf += "\t~_FIN() { if (rethrow) objc_exception_throw(rethrow); }\n"; 01813 buf += "\tid rethrow;\n"; 01814 buf += "\t} _fin_force_rethow(_rethrow);"; 01815 } 01816 01817 /// RewriteObjCSynchronizedStmt - 01818 /// This routine rewrites @synchronized(expr) stmt; 01819 /// into: 01820 /// objc_sync_enter(expr); 01821 /// @try stmt @finally { objc_sync_exit(expr); } 01822 /// 01823 Stmt *RewriteModernObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { 01824 // Get the start location and compute the semi location. 01825 SourceLocation startLoc = S->getLocStart(); 01826 const char *startBuf = SM->getCharacterData(startLoc); 01827 01828 assert((*startBuf == '@') && "bogus @synchronized location"); 01829 01830 std::string buf; 01831 buf = "{ id _rethrow = 0; id _sync_obj = "; 01832 01833 const char *lparenBuf = startBuf; 01834 while (*lparenBuf != '(') lparenBuf++; 01835 ReplaceText(startLoc, lparenBuf-startBuf+1, buf); 01836 01837 buf = "; objc_sync_enter(_sync_obj);\n"; 01838 buf += "try {\n\tstruct _SYNC_EXIT { _SYNC_EXIT(id arg) : sync_exit(arg) {}"; 01839 buf += "\n\t~_SYNC_EXIT() {objc_sync_exit(sync_exit);}"; 01840 buf += "\n\tid sync_exit;"; 01841 buf += "\n\t} _sync_exit(_sync_obj);\n"; 01842 01843 // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since 01844 // the sync expression is typically a message expression that's already 01845 // been rewritten! (which implies the SourceLocation's are invalid). 01846 SourceLocation RParenExprLoc = S->getSynchBody()->getLocStart(); 01847 const char *RParenExprLocBuf = SM->getCharacterData(RParenExprLoc); 01848 while (*RParenExprLocBuf != ')') RParenExprLocBuf--; 01849 RParenExprLoc = startLoc.getLocWithOffset(RParenExprLocBuf-startBuf); 01850 01851 SourceLocation LBranceLoc = S->getSynchBody()->getLocStart(); 01852 const char *LBraceLocBuf = SM->getCharacterData(LBranceLoc); 01853 assert (*LBraceLocBuf == '{'); 01854 ReplaceText(RParenExprLoc, (LBraceLocBuf - SM->getCharacterData(RParenExprLoc) + 1), buf); 01855 01856 SourceLocation startRBraceLoc = S->getSynchBody()->getLocEnd(); 01857 assert((*SM->getCharacterData(startRBraceLoc) == '}') && 01858 "bogus @synchronized block"); 01859 01860 buf = "} catch (id e) {_rethrow = e;}\n"; 01861 Write_RethrowObject(buf); 01862 buf += "}\n"; 01863 buf += "}\n"; 01864 01865 ReplaceText(startRBraceLoc, 1, buf); 01866 01867 return 0; 01868 } 01869 01870 void RewriteModernObjC::WarnAboutReturnGotoStmts(Stmt *S) 01871 { 01872 // Perform a bottom up traversal of all children. 01873 for (Stmt::child_range CI = S->children(); CI; ++CI) 01874 if (*CI) 01875 WarnAboutReturnGotoStmts(*CI); 01876 01877 if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) { 01878 Diags.Report(Context->getFullLoc(S->getLocStart()), 01879 TryFinallyContainsReturnDiag); 01880 } 01881 return; 01882 } 01883 01884 Stmt *RewriteModernObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { 01885 ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt(); 01886 bool noCatch = S->getNumCatchStmts() == 0; 01887 std::string buf; 01888 01889 if (finalStmt) { 01890 if (noCatch) 01891 buf = "{ id volatile _rethrow = 0;\n"; 01892 else { 01893 buf = "{ id volatile _rethrow = 0;\ntry {\n"; 01894 } 01895 } 01896 // Get the start location and compute the semi location. 01897 SourceLocation startLoc = S->getLocStart(); 01898 const char *startBuf = SM->getCharacterData(startLoc); 01899 01900 assert((*startBuf == '@') && "bogus @try location"); 01901 if (finalStmt) 01902 ReplaceText(startLoc, 1, buf); 01903 else 01904 // @try -> try 01905 ReplaceText(startLoc, 1, ""); 01906 01907 for (unsigned I = 0, N = S->getNumCatchStmts(); I != N; ++I) { 01908 ObjCAtCatchStmt *Catch = S->getCatchStmt(I); 01909 VarDecl *catchDecl = Catch->getCatchParamDecl(); 01910 01911 startLoc = Catch->getLocStart(); 01912 bool AtRemoved = false; 01913 if (catchDecl) { 01914 QualType t = catchDecl->getType(); 01915 if (const ObjCObjectPointerType *Ptr = t->getAs<ObjCObjectPointerType>()) { 01916 // Should be a pointer to a class. 01917 ObjCInterfaceDecl *IDecl = Ptr->getObjectType()->getInterface(); 01918 if (IDecl) { 01919 std::string Result; 01920 startBuf = SM->getCharacterData(startLoc); 01921 assert((*startBuf == '@') && "bogus @catch location"); 01922 SourceLocation rParenLoc = Catch->getRParenLoc(); 01923 const char *rParenBuf = SM->getCharacterData(rParenLoc); 01924 01925 // _objc_exc_Foo *_e as argument to catch. 01926 Result = "catch (_objc_exc_"; Result += IDecl->getNameAsString(); 01927 Result += " *_"; Result += catchDecl->getNameAsString(); 01928 Result += ")"; 01929 ReplaceText(startLoc, rParenBuf-startBuf+1, Result); 01930 // Foo *e = (Foo *)_e; 01931 Result.clear(); 01932 Result = "{ "; 01933 Result += IDecl->getNameAsString(); 01934 Result += " *"; Result += catchDecl->getNameAsString(); 01935 Result += " = ("; Result += IDecl->getNameAsString(); Result += "*)"; 01936 Result += "_"; Result += catchDecl->getNameAsString(); 01937 01938 Result += "; "; 01939 SourceLocation lBraceLoc = Catch->getCatchBody()->getLocStart(); 01940 ReplaceText(lBraceLoc, 1, Result); 01941 AtRemoved = true; 01942 } 01943 } 01944 } 01945 if (!AtRemoved) 01946 // @catch -> catch 01947 ReplaceText(startLoc, 1, ""); 01948 01949 } 01950 if (finalStmt) { 01951 buf.clear(); 01952 if (noCatch) 01953 buf = "catch (id e) {_rethrow = e;}\n"; 01954 else 01955 buf = "}\ncatch (id e) {_rethrow = e;}\n"; 01956 01957 SourceLocation startFinalLoc = finalStmt->getLocStart(); 01958 ReplaceText(startFinalLoc, 8, buf); 01959 Stmt *body = finalStmt->getFinallyBody(); 01960 SourceLocation startFinalBodyLoc = body->getLocStart(); 01961 buf.clear(); 01962 Write_RethrowObject(buf); 01963 ReplaceText(startFinalBodyLoc, 1, buf); 01964 01965 SourceLocation endFinalBodyLoc = body->getLocEnd(); 01966 ReplaceText(endFinalBodyLoc, 1, "}\n}"); 01967 // Now check for any return/continue/go statements within the @try. 01968 WarnAboutReturnGotoStmts(S->getTryBody()); 01969 } 01970 01971 return 0; 01972 } 01973 01974 // This can't be done with ReplaceStmt(S, ThrowExpr), since 01975 // the throw expression is typically a message expression that's already 01976 // been rewritten! (which implies the SourceLocation's are invalid). 01977 Stmt *RewriteModernObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { 01978 // Get the start location and compute the semi location. 01979 SourceLocation startLoc = S->getLocStart(); 01980 const char *startBuf = SM->getCharacterData(startLoc); 01981 01982 assert((*startBuf == '@') && "bogus @throw location"); 01983 01984 std::string buf; 01985 /* void objc_exception_throw(id) __attribute__((noreturn)); */ 01986 if (S->getThrowExpr()) 01987 buf = "objc_exception_throw("; 01988 else 01989 buf = "throw"; 01990 01991 // handle "@ throw" correctly. 01992 const char *wBuf = strchr(startBuf, 'w'); 01993 assert((*wBuf == 'w') && "@throw: can't find 'w'"); 01994 ReplaceText(startLoc, wBuf-startBuf+1, buf); 01995 01996 const char *semiBuf = strchr(startBuf, ';'); 01997 assert((*semiBuf == ';') && "@throw: can't find ';'"); 01998 SourceLocation semiLoc = startLoc.getLocWithOffset(semiBuf-startBuf); 01999 if (S->getThrowExpr()) 02000 ReplaceText(semiLoc, 1, ");"); 02001 return 0; 02002 } 02003 02004 Stmt *RewriteModernObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) { 02005 // Create a new string expression. 02006 QualType StrType = Context->getPointerType(Context->CharTy); 02007 std::string StrEncoding; 02008 Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding); 02009 Expr *Replacement = StringLiteral::Create(*Context, StrEncoding, 02010 StringLiteral::Ascii, false, 02011 StrType, SourceLocation()); 02012 ReplaceStmt(Exp, Replacement); 02013 02014 // Replace this subexpr in the parent. 02015 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 02016 return Replacement; 02017 } 02018 02019 Stmt *RewriteModernObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) { 02020 if (!SelGetUidFunctionDecl) 02021 SynthSelGetUidFunctionDecl(); 02022 assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl"); 02023 // Create a call to sel_registerName("selName"). 02024 SmallVector<Expr*, 8> SelExprs; 02025 QualType argType = Context->getPointerType(Context->CharTy); 02026 SelExprs.push_back(StringLiteral::Create(*Context, 02027 Exp->getSelector().getAsString(), 02028 StringLiteral::Ascii, false, 02029 argType, SourceLocation())); 02030 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 02031 &SelExprs[0], SelExprs.size()); 02032 ReplaceStmt(Exp, SelExp); 02033 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 02034 return SelExp; 02035 } 02036 02037 CallExpr *RewriteModernObjC::SynthesizeCallToFunctionDecl( 02038 FunctionDecl *FD, Expr **args, unsigned nargs, SourceLocation StartLoc, 02039 SourceLocation EndLoc) { 02040 // Get the type, we will need to reference it in a couple spots. 02041 QualType msgSendType = FD->getType(); 02042 02043 // Create a reference to the objc_msgSend() declaration. 02044 DeclRefExpr *DRE = 02045 new (Context) DeclRefExpr(FD, false, msgSendType, VK_LValue, SourceLocation()); 02046 02047 // Now, we cast the reference to a pointer to the objc_msgSend type. 02048 QualType pToFunc = Context->getPointerType(msgSendType); 02049 ImplicitCastExpr *ICE = 02050 ImplicitCastExpr::Create(*Context, pToFunc, CK_FunctionToPointerDecay, 02051 DRE, 0, VK_RValue); 02052 02053 const FunctionType *FT = msgSendType->getAs<FunctionType>(); 02054 02055 CallExpr *Exp = 02056 new (Context) CallExpr(*Context, ICE, args, nargs, 02057 FT->getCallResultType(*Context), 02058 VK_RValue, EndLoc); 02059 return Exp; 02060 } 02061 02062 static bool scanForProtocolRefs(const char *startBuf, const char *endBuf, 02063 const char *&startRef, const char *&endRef) { 02064 while (startBuf < endBuf) { 02065 if (*startBuf == '<') 02066 startRef = startBuf; // mark the start. 02067 if (*startBuf == '>') { 02068 if (startRef && *startRef == '<') { 02069 endRef = startBuf; // mark the end. 02070 return true; 02071 } 02072 return false; 02073 } 02074 startBuf++; 02075 } 02076 return false; 02077 } 02078 02079 static void scanToNextArgument(const char *&argRef) { 02080 int angle = 0; 02081 while (*argRef != ')' && (*argRef != ',' || angle > 0)) { 02082 if (*argRef == '<') 02083 angle++; 02084 else if (*argRef == '>') 02085 angle--; 02086 argRef++; 02087 } 02088 assert(angle == 0 && "scanToNextArgument - bad protocol type syntax"); 02089 } 02090 02091 bool RewriteModernObjC::needToScanForQualifiers(QualType T) { 02092 if (T->isObjCQualifiedIdType()) 02093 return true; 02094 if (const PointerType *PT = T->getAs<PointerType>()) { 02095 if (PT->getPointeeType()->isObjCQualifiedIdType()) 02096 return true; 02097 } 02098 if (T->isObjCObjectPointerType()) { 02099 T = T->getPointeeType(); 02100 return T->isObjCQualifiedInterfaceType(); 02101 } 02102 if (T->isArrayType()) { 02103 QualType ElemTy = Context->getBaseElementType(T); 02104 return needToScanForQualifiers(ElemTy); 02105 } 02106 return false; 02107 } 02108 02109 void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { 02110 QualType Type = E->getType(); 02111 if (needToScanForQualifiers(Type)) { 02112 SourceLocation Loc, EndLoc; 02113 02114 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) { 02115 Loc = ECE->getLParenLoc(); 02116 EndLoc = ECE->getRParenLoc(); 02117 } else { 02118 Loc = E->getLocStart(); 02119 EndLoc = E->getLocEnd(); 02120 } 02121 // This will defend against trying to rewrite synthesized expressions. 02122 if (Loc.isInvalid() || EndLoc.isInvalid()) 02123 return; 02124 02125 const char *startBuf = SM->getCharacterData(Loc); 02126 const char *endBuf = SM->getCharacterData(EndLoc); 02127 const char *startRef = 0, *endRef = 0; 02128 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 02129 // Get the locations of the startRef, endRef. 02130 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-startBuf); 02131 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-startBuf+1); 02132 // Comment out the protocol references. 02133 InsertText(LessLoc, "/*"); 02134 InsertText(GreaterLoc, "*/"); 02135 } 02136 } 02137 } 02138 02139 void RewriteModernObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { 02140 SourceLocation Loc; 02141 QualType Type; 02142 const FunctionProtoType *proto = 0; 02143 if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) { 02144 Loc = VD->getLocation(); 02145 Type = VD->getType(); 02146 } 02147 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) { 02148 Loc = FD->getLocation(); 02149 // Check for ObjC 'id' and class types that have been adorned with protocol 02150 // information (id<p>, C<p>*). The protocol references need to be rewritten! 02151 const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 02152 assert(funcType && "missing function type"); 02153 proto = dyn_cast<FunctionProtoType>(funcType); 02154 if (!proto) 02155 return; 02156 Type = proto->getResultType(); 02157 } 02158 else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) { 02159 Loc = FD->getLocation(); 02160 Type = FD->getType(); 02161 } 02162 else 02163 return; 02164 02165 if (needToScanForQualifiers(Type)) { 02166 // Since types are unique, we need to scan the buffer. 02167 02168 const char *endBuf = SM->getCharacterData(Loc); 02169 const char *startBuf = endBuf; 02170 while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart) 02171 startBuf--; // scan backward (from the decl location) for return type. 02172 const char *startRef = 0, *endRef = 0; 02173 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 02174 // Get the locations of the startRef, endRef. 02175 SourceLocation LessLoc = Loc.getLocWithOffset(startRef-endBuf); 02176 SourceLocation GreaterLoc = Loc.getLocWithOffset(endRef-endBuf+1); 02177 // Comment out the protocol references. 02178 InsertText(LessLoc, "/*"); 02179 InsertText(GreaterLoc, "*/"); 02180 } 02181 } 02182 if (!proto) 02183 return; // most likely, was a variable 02184 // Now check arguments. 02185 const char *startBuf = SM->getCharacterData(Loc); 02186 const char *startFuncBuf = startBuf; 02187 for (unsigned i = 0; i < proto->getNumArgs(); i++) { 02188 if (needToScanForQualifiers(proto->getArgType(i))) { 02189 // Since types are unique, we need to scan the buffer. 02190 02191 const char *endBuf = startBuf; 02192 // scan forward (from the decl location) for argument types. 02193 scanToNextArgument(endBuf); 02194 const char *startRef = 0, *endRef = 0; 02195 if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) { 02196 // Get the locations of the startRef, endRef. 02197 SourceLocation LessLoc = 02198 Loc.getLocWithOffset(startRef-startFuncBuf); 02199 SourceLocation GreaterLoc = 02200 Loc.getLocWithOffset(endRef-startFuncBuf+1); 02201 // Comment out the protocol references. 02202 InsertText(LessLoc, "/*"); 02203 InsertText(GreaterLoc, "*/"); 02204 } 02205 startBuf = ++endBuf; 02206 } 02207 else { 02208 // If the function name is derived from a macro expansion, then the 02209 // argument buffer will not follow the name. Need to speak with Chris. 02210 while (*startBuf && *startBuf != ')' && *startBuf != ',') 02211 startBuf++; // scan forward (from the decl location) for argument types. 02212 startBuf++; 02213 } 02214 } 02215 } 02216 02217 void RewriteModernObjC::RewriteTypeOfDecl(VarDecl *ND) { 02218 QualType QT = ND->getType(); 02219 const Type* TypePtr = QT->getAs<Type>(); 02220 if (!isa<TypeOfExprType>(TypePtr)) 02221 return; 02222 while (isa<TypeOfExprType>(TypePtr)) { 02223 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 02224 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 02225 TypePtr = QT->getAs<Type>(); 02226 } 02227 // FIXME. This will not work for multiple declarators; as in: 02228 // __typeof__(a) b,c,d; 02229 std::string TypeAsString(QT.getAsString(Context->getPrintingPolicy())); 02230 SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 02231 const char *startBuf = SM->getCharacterData(DeclLoc); 02232 if (ND->getInit()) { 02233 std::string Name(ND->getNameAsString()); 02234 TypeAsString += " " + Name + " = "; 02235 Expr *E = ND->getInit(); 02236 SourceLocation startLoc; 02237 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 02238 startLoc = ECE->getLParenLoc(); 02239 else 02240 startLoc = E->getLocStart(); 02241 startLoc = SM->getExpansionLoc(startLoc); 02242 const char *endBuf = SM->getCharacterData(startLoc); 02243 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 02244 } 02245 else { 02246 SourceLocation X = ND->getLocEnd(); 02247 X = SM->getExpansionLoc(X); 02248 const char *endBuf = SM->getCharacterData(X); 02249 ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); 02250 } 02251 } 02252 02253 // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); 02254 void RewriteModernObjC::SynthSelGetUidFunctionDecl() { 02255 IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); 02256 SmallVector<QualType, 16> ArgTys; 02257 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 02258 QualType getFuncType = 02259 getSimpleFunctionType(Context->getObjCSelType(), &ArgTys[0], ArgTys.size()); 02260 SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02261 SourceLocation(), 02262 SourceLocation(), 02263 SelGetUidIdent, getFuncType, 0, 02264 SC_Extern, 02265 SC_None, false); 02266 } 02267 02268 void RewriteModernObjC::RewriteFunctionDecl(FunctionDecl *FD) { 02269 // declared in <objc/objc.h> 02270 if (FD->getIdentifier() && 02271 FD->getName() == "sel_registerName") { 02272 SelGetUidFunctionDecl = FD; 02273 return; 02274 } 02275 RewriteObjCQualifiedInterfaceTypes(FD); 02276 } 02277 02278 void RewriteModernObjC::RewriteBlockPointerType(std::string& Str, QualType Type) { 02279 std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 02280 const char *argPtr = TypeString.c_str(); 02281 if (!strchr(argPtr, '^')) { 02282 Str += TypeString; 02283 return; 02284 } 02285 while (*argPtr) { 02286 Str += (*argPtr == '^' ? '*' : *argPtr); 02287 argPtr++; 02288 } 02289 } 02290 02291 // FIXME. Consolidate this routine with RewriteBlockPointerType. 02292 void RewriteModernObjC::RewriteBlockPointerTypeVariable(std::string& Str, 02293 ValueDecl *VD) { 02294 QualType Type = VD->getType(); 02295 std::string TypeString(Type.getAsString(Context->getPrintingPolicy())); 02296 const char *argPtr = TypeString.c_str(); 02297 int paren = 0; 02298 while (*argPtr) { 02299 switch (*argPtr) { 02300 case '(': 02301 Str += *argPtr; 02302 paren++; 02303 break; 02304 case ')': 02305 Str += *argPtr; 02306 paren--; 02307 break; 02308 case '^': 02309 Str += '*'; 02310 if (paren == 1) 02311 Str += VD->getNameAsString(); 02312 break; 02313 default: 02314 Str += *argPtr; 02315 break; 02316 } 02317 argPtr++; 02318 } 02319 } 02320 02321 void RewriteModernObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { 02322 SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); 02323 const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); 02324 const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType); 02325 if (!proto) 02326 return; 02327 QualType Type = proto->getResultType(); 02328 std::string FdStr = Type.getAsString(Context->getPrintingPolicy()); 02329 FdStr += " "; 02330 FdStr += FD->getName(); 02331 FdStr += "("; 02332 unsigned numArgs = proto->getNumArgs(); 02333 for (unsigned i = 0; i < numArgs; i++) { 02334 QualType ArgType = proto->getArgType(i); 02335 RewriteBlockPointerType(FdStr, ArgType); 02336 if (i+1 < numArgs) 02337 FdStr += ", "; 02338 } 02339 if (FD->isVariadic()) { 02340 FdStr += (numArgs > 0) ? ", ...);\n" : "...);\n"; 02341 } 02342 else 02343 FdStr += ");\n"; 02344 InsertText(FunLocStart, FdStr); 02345 } 02346 02347 // SynthSuperContructorFunctionDecl - id __rw_objc_super(id obj, id super); 02348 void RewriteModernObjC::SynthSuperContructorFunctionDecl() { 02349 if (SuperContructorFunctionDecl) 02350 return; 02351 IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super"); 02352 SmallVector<QualType, 16> ArgTys; 02353 QualType argT = Context->getObjCIdType(); 02354 assert(!argT.isNull() && "Can't find 'id' type"); 02355 ArgTys.push_back(argT); 02356 ArgTys.push_back(argT); 02357 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 02358 &ArgTys[0], ArgTys.size()); 02359 SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02360 SourceLocation(), 02361 SourceLocation(), 02362 msgSendIdent, msgSendType, 0, 02363 SC_Extern, 02364 SC_None, false); 02365 } 02366 02367 // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...); 02368 void RewriteModernObjC::SynthMsgSendFunctionDecl() { 02369 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend"); 02370 SmallVector<QualType, 16> ArgTys; 02371 QualType argT = Context->getObjCIdType(); 02372 assert(!argT.isNull() && "Can't find 'id' type"); 02373 ArgTys.push_back(argT); 02374 argT = Context->getObjCSelType(); 02375 assert(!argT.isNull() && "Can't find 'SEL' type"); 02376 ArgTys.push_back(argT); 02377 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 02378 &ArgTys[0], ArgTys.size(), 02379 true /*isVariadic*/); 02380 MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02381 SourceLocation(), 02382 SourceLocation(), 02383 msgSendIdent, msgSendType, 0, 02384 SC_Extern, 02385 SC_None, false); 02386 } 02387 02388 // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(void); 02389 void RewriteModernObjC::SynthMsgSendSuperFunctionDecl() { 02390 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper"); 02391 SmallVector<QualType, 2> ArgTys; 02392 ArgTys.push_back(Context->VoidTy); 02393 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 02394 &ArgTys[0], 1, 02395 true /*isVariadic*/); 02396 MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02397 SourceLocation(), 02398 SourceLocation(), 02399 msgSendIdent, msgSendType, 0, 02400 SC_Extern, 02401 SC_None, false); 02402 } 02403 02404 // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...); 02405 void RewriteModernObjC::SynthMsgSendStretFunctionDecl() { 02406 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret"); 02407 SmallVector<QualType, 16> ArgTys; 02408 QualType argT = Context->getObjCIdType(); 02409 assert(!argT.isNull() && "Can't find 'id' type"); 02410 ArgTys.push_back(argT); 02411 argT = Context->getObjCSelType(); 02412 assert(!argT.isNull() && "Can't find 'SEL' type"); 02413 ArgTys.push_back(argT); 02414 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 02415 &ArgTys[0], ArgTys.size(), 02416 true /*isVariadic*/); 02417 MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02418 SourceLocation(), 02419 SourceLocation(), 02420 msgSendIdent, msgSendType, 0, 02421 SC_Extern, 02422 SC_None, false); 02423 } 02424 02425 // SynthMsgSendSuperStretFunctionDecl - 02426 // id objc_msgSendSuper_stret(void); 02427 void RewriteModernObjC::SynthMsgSendSuperStretFunctionDecl() { 02428 IdentifierInfo *msgSendIdent = 02429 &Context->Idents.get("objc_msgSendSuper_stret"); 02430 SmallVector<QualType, 2> ArgTys; 02431 ArgTys.push_back(Context->VoidTy); 02432 QualType msgSendType = getSimpleFunctionType(Context->getObjCIdType(), 02433 &ArgTys[0], 1, 02434 true /*isVariadic*/); 02435 MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02436 SourceLocation(), 02437 SourceLocation(), 02438 msgSendIdent, msgSendType, 0, 02439 SC_Extern, 02440 SC_None, false); 02441 } 02442 02443 // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...); 02444 void RewriteModernObjC::SynthMsgSendFpretFunctionDecl() { 02445 IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret"); 02446 SmallVector<QualType, 16> ArgTys; 02447 QualType argT = Context->getObjCIdType(); 02448 assert(!argT.isNull() && "Can't find 'id' type"); 02449 ArgTys.push_back(argT); 02450 argT = Context->getObjCSelType(); 02451 assert(!argT.isNull() && "Can't find 'SEL' type"); 02452 ArgTys.push_back(argT); 02453 QualType msgSendType = getSimpleFunctionType(Context->DoubleTy, 02454 &ArgTys[0], ArgTys.size(), 02455 true /*isVariadic*/); 02456 MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02457 SourceLocation(), 02458 SourceLocation(), 02459 msgSendIdent, msgSendType, 0, 02460 SC_Extern, 02461 SC_None, false); 02462 } 02463 02464 // SynthGetClassFunctionDecl - Class objc_getClass(const char *name); 02465 void RewriteModernObjC::SynthGetClassFunctionDecl() { 02466 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass"); 02467 SmallVector<QualType, 16> ArgTys; 02468 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 02469 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 02470 &ArgTys[0], ArgTys.size()); 02471 GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02472 SourceLocation(), 02473 SourceLocation(), 02474 getClassIdent, getClassType, 0, 02475 SC_Extern, 02476 SC_None, false); 02477 } 02478 02479 // SynthGetSuperClassFunctionDecl - Class class_getSuperclass(Class cls); 02480 void RewriteModernObjC::SynthGetSuperClassFunctionDecl() { 02481 IdentifierInfo *getSuperClassIdent = 02482 &Context->Idents.get("class_getSuperclass"); 02483 SmallVector<QualType, 16> ArgTys; 02484 ArgTys.push_back(Context->getObjCClassType()); 02485 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 02486 &ArgTys[0], ArgTys.size()); 02487 GetSuperClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02488 SourceLocation(), 02489 SourceLocation(), 02490 getSuperClassIdent, 02491 getClassType, 0, 02492 SC_Extern, 02493 SC_None, 02494 false); 02495 } 02496 02497 // SynthGetMetaClassFunctionDecl - Class objc_getMetaClass(const char *name); 02498 void RewriteModernObjC::SynthGetMetaClassFunctionDecl() { 02499 IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); 02500 SmallVector<QualType, 16> ArgTys; 02501 ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst())); 02502 QualType getClassType = getSimpleFunctionType(Context->getObjCClassType(), 02503 &ArgTys[0], ArgTys.size()); 02504 GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl, 02505 SourceLocation(), 02506 SourceLocation(), 02507 getClassIdent, getClassType, 0, 02508 SC_Extern, 02509 SC_None, false); 02510 } 02511 02512 Stmt *RewriteModernObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { 02513 QualType strType = getConstantStringStructType(); 02514 02515 std::string S = "__NSConstantStringImpl_"; 02516 02517 std::string tmpName = InFileName; 02518 unsigned i; 02519 for (i=0; i < tmpName.length(); i++) { 02520 char c = tmpName.at(i); 02521 // replace any non alphanumeric characters with '_'. 02522 if (!isalpha(c) && (c < '0' || c > '9')) 02523 tmpName[i] = '_'; 02524 } 02525 S += tmpName; 02526 S += "_"; 02527 S += utostr(NumObjCStringLiterals++); 02528 02529 Preamble += "static __NSConstantStringImpl " + S; 02530 Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,"; 02531 Preamble += "0x000007c8,"; // utf8_str 02532 // The pretty printer for StringLiteral handles escape characters properly. 02533 std::string prettyBufS; 02534 llvm::raw_string_ostream prettyBuf(prettyBufS); 02535 Exp->getString()->printPretty(prettyBuf, *Context, 0, 02536 PrintingPolicy(LangOpts)); 02537 Preamble += prettyBuf.str(); 02538 Preamble += ","; 02539 Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; 02540 02541 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 02542 SourceLocation(), &Context->Idents.get(S), 02543 strType, 0, SC_Static, SC_None); 02544 DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue, 02545 SourceLocation()); 02546 Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, 02547 Context->getPointerType(DRE->getType()), 02548 VK_RValue, OK_Ordinary, 02549 SourceLocation()); 02550 // cast to NSConstantString * 02551 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(), 02552 CK_CPointerToObjCPointerCast, Unop); 02553 ReplaceStmt(Exp, cast); 02554 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 02555 return cast; 02556 } 02557 02558 Stmt *RewriteModernObjC::RewriteObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Exp) { 02559 unsigned IntSize = 02560 static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 02561 02562 Expr *FlagExp = IntegerLiteral::Create(*Context, 02563 llvm::APInt(IntSize, Exp->getValue()), 02564 Context->IntTy, Exp->getLocation()); 02565 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Context->ObjCBuiltinBoolTy, 02566 CK_BitCast, FlagExp); 02567 ParenExpr *PE = new (Context) ParenExpr(Exp->getLocation(), Exp->getExprLoc(), 02568 cast); 02569 ReplaceStmt(Exp, PE); 02570 return PE; 02571 } 02572 02573 Stmt *RewriteModernObjC::RewriteObjCBoxedExpr(ObjCBoxedExpr *Exp) { 02574 // synthesize declaration of helper functions needed in this routine. 02575 if (!SelGetUidFunctionDecl) 02576 SynthSelGetUidFunctionDecl(); 02577 // use objc_msgSend() for all. 02578 if (!MsgSendFunctionDecl) 02579 SynthMsgSendFunctionDecl(); 02580 if (!GetClassFunctionDecl) 02581 SynthGetClassFunctionDecl(); 02582 02583 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 02584 SourceLocation StartLoc = Exp->getLocStart(); 02585 SourceLocation EndLoc = Exp->getLocEnd(); 02586 02587 // Synthesize a call to objc_msgSend(). 02588 SmallVector<Expr*, 4> MsgExprs; 02589 SmallVector<Expr*, 4> ClsExprs; 02590 QualType argType = Context->getPointerType(Context->CharTy); 02591 02592 // Create a call to objc_getClass("<BoxingClass>"). It will be the 1st argument. 02593 ObjCMethodDecl *BoxingMethod = Exp->getBoxingMethod(); 02594 ObjCInterfaceDecl *BoxingClass = BoxingMethod->getClassInterface(); 02595 02596 IdentifierInfo *clsName = BoxingClass->getIdentifier(); 02597 ClsExprs.push_back(StringLiteral::Create(*Context, 02598 clsName->getName(), 02599 StringLiteral::Ascii, false, 02600 argType, SourceLocation())); 02601 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 02602 &ClsExprs[0], 02603 ClsExprs.size(), 02604 StartLoc, EndLoc); 02605 MsgExprs.push_back(Cls); 02606 02607 // Create a call to sel_registerName("<BoxingMethod>:"), etc. 02608 // it will be the 2nd argument. 02609 SmallVector<Expr*, 4> SelExprs; 02610 SelExprs.push_back(StringLiteral::Create(*Context, 02611 BoxingMethod->getSelector().getAsString(), 02612 StringLiteral::Ascii, false, 02613 argType, SourceLocation())); 02614 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 02615 &SelExprs[0], SelExprs.size(), 02616 StartLoc, EndLoc); 02617 MsgExprs.push_back(SelExp); 02618 02619 // User provided sub-expression is the 3rd, and last, argument. 02620 Expr *subExpr = Exp->getSubExpr(); 02621 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(subExpr)) { 02622 QualType type = ICE->getType(); 02623 const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 02624 CastKind CK = CK_BitCast; 02625 if (SubExpr->getType()->isIntegralType(*Context) && type->isBooleanType()) 02626 CK = CK_IntegralToBoolean; 02627 subExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, subExpr); 02628 } 02629 MsgExprs.push_back(subExpr); 02630 02631 SmallVector<QualType, 4> ArgTypes; 02632 ArgTypes.push_back(Context->getObjCIdType()); 02633 ArgTypes.push_back(Context->getObjCSelType()); 02634 for (ObjCMethodDecl::param_iterator PI = BoxingMethod->param_begin(), 02635 E = BoxingMethod->param_end(); PI != E; ++PI) 02636 ArgTypes.push_back((*PI)->getType()); 02637 02638 QualType returnType = Exp->getType(); 02639 // Get the type, we will need to reference it in a couple spots. 02640 QualType msgSendType = MsgSendFlavor->getType(); 02641 02642 // Create a reference to the objc_msgSend() declaration. 02643 DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 02644 VK_LValue, SourceLocation()); 02645 02646 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, 02647 Context->getPointerType(Context->VoidTy), 02648 CK_BitCast, DRE); 02649 02650 // Now do the "normal" pointer to function cast. 02651 QualType castType = 02652 getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 02653 BoxingMethod->isVariadic()); 02654 castType = Context->getPointerType(castType); 02655 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 02656 cast); 02657 02658 // Don't forget the parens to enforce the proper binding. 02659 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 02660 02661 const FunctionType *FT = msgSendType->getAs<FunctionType>(); 02662 CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 02663 MsgExprs.size(), 02664 FT->getResultType(), VK_RValue, 02665 EndLoc); 02666 ReplaceStmt(Exp, CE); 02667 return CE; 02668 } 02669 02670 Stmt *RewriteModernObjC::RewriteObjCArrayLiteralExpr(ObjCArrayLiteral *Exp) { 02671 // synthesize declaration of helper functions needed in this routine. 02672 if (!SelGetUidFunctionDecl) 02673 SynthSelGetUidFunctionDecl(); 02674 // use objc_msgSend() for all. 02675 if (!MsgSendFunctionDecl) 02676 SynthMsgSendFunctionDecl(); 02677 if (!GetClassFunctionDecl) 02678 SynthGetClassFunctionDecl(); 02679 02680 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 02681 SourceLocation StartLoc = Exp->getLocStart(); 02682 SourceLocation EndLoc = Exp->getLocEnd(); 02683 02684 // Build the expression: __NSContainer_literal(int, ...).arr 02685 QualType IntQT = Context->IntTy; 02686 QualType NSArrayFType = 02687 getSimpleFunctionType(Context->VoidTy, &IntQT, 1, true); 02688 std::string NSArrayFName("__NSContainer_literal"); 02689 FunctionDecl *NSArrayFD = SynthBlockInitFunctionDecl(NSArrayFName); 02690 DeclRefExpr *NSArrayDRE = 02691 new (Context) DeclRefExpr(NSArrayFD, false, NSArrayFType, VK_RValue, 02692 SourceLocation()); 02693 02694 SmallVector<Expr*, 16> InitExprs; 02695 unsigned NumElements = Exp->getNumElements(); 02696 unsigned UnsignedIntSize = 02697 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 02698 Expr *count = IntegerLiteral::Create(*Context, 02699 llvm::APInt(UnsignedIntSize, NumElements), 02700 Context->UnsignedIntTy, SourceLocation()); 02701 InitExprs.push_back(count); 02702 for (unsigned i = 0; i < NumElements; i++) 02703 InitExprs.push_back(Exp->getElement(i)); 02704 Expr *NSArrayCallExpr = 02705 new (Context) CallExpr(*Context, NSArrayDRE, &InitExprs[0], InitExprs.size(), 02706 NSArrayFType, VK_LValue, SourceLocation()); 02707 02708 FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(), 02709 SourceLocation(), 02710 &Context->Idents.get("arr"), 02711 Context->getPointerType(Context->VoidPtrTy), 0, 02712 /*BitWidth=*/0, /*Mutable=*/true, 02713 /*HasInit=*/false); 02714 MemberExpr *ArrayLiteralME = 02715 new (Context) MemberExpr(NSArrayCallExpr, false, ARRFD, 02716 SourceLocation(), 02717 ARRFD->getType(), VK_LValue, 02718 OK_Ordinary); 02719 QualType ConstIdT = Context->getObjCIdType().withConst(); 02720 CStyleCastExpr * ArrayLiteralObjects = 02721 NoTypeInfoCStyleCastExpr(Context, 02722 Context->getPointerType(ConstIdT), 02723 CK_BitCast, 02724 ArrayLiteralME); 02725 02726 // Synthesize a call to objc_msgSend(). 02727 SmallVector<Expr*, 32> MsgExprs; 02728 SmallVector<Expr*, 4> ClsExprs; 02729 QualType argType = Context->getPointerType(Context->CharTy); 02730 QualType expType = Exp->getType(); 02731 02732 // Create a call to objc_getClass("NSArray"). It will be th 1st argument. 02733 ObjCInterfaceDecl *Class = 02734 expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface(); 02735 02736 IdentifierInfo *clsName = Class->getIdentifier(); 02737 ClsExprs.push_back(StringLiteral::Create(*Context, 02738 clsName->getName(), 02739 StringLiteral::Ascii, false, 02740 argType, SourceLocation())); 02741 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 02742 &ClsExprs[0], 02743 ClsExprs.size(), 02744 StartLoc, EndLoc); 02745 MsgExprs.push_back(Cls); 02746 02747 // Create a call to sel_registerName("arrayWithObjects:count:"). 02748 // it will be the 2nd argument. 02749 SmallVector<Expr*, 4> SelExprs; 02750 ObjCMethodDecl *ArrayMethod = Exp->getArrayWithObjectsMethod(); 02751 SelExprs.push_back(StringLiteral::Create(*Context, 02752 ArrayMethod->getSelector().getAsString(), 02753 StringLiteral::Ascii, false, 02754 argType, SourceLocation())); 02755 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 02756 &SelExprs[0], SelExprs.size(), 02757 StartLoc, EndLoc); 02758 MsgExprs.push_back(SelExp); 02759 02760 // (const id [])objects 02761 MsgExprs.push_back(ArrayLiteralObjects); 02762 02763 // (NSUInteger)cnt 02764 Expr *cnt = IntegerLiteral::Create(*Context, 02765 llvm::APInt(UnsignedIntSize, NumElements), 02766 Context->UnsignedIntTy, SourceLocation()); 02767 MsgExprs.push_back(cnt); 02768 02769 02770 SmallVector<QualType, 4> ArgTypes; 02771 ArgTypes.push_back(Context->getObjCIdType()); 02772 ArgTypes.push_back(Context->getObjCSelType()); 02773 for (ObjCMethodDecl::param_iterator PI = ArrayMethod->param_begin(), 02774 E = ArrayMethod->param_end(); PI != E; ++PI) 02775 ArgTypes.push_back((*PI)->getType()); 02776 02777 QualType returnType = Exp->getType(); 02778 // Get the type, we will need to reference it in a couple spots. 02779 QualType msgSendType = MsgSendFlavor->getType(); 02780 02781 // Create a reference to the objc_msgSend() declaration. 02782 DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 02783 VK_LValue, SourceLocation()); 02784 02785 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, 02786 Context->getPointerType(Context->VoidTy), 02787 CK_BitCast, DRE); 02788 02789 // Now do the "normal" pointer to function cast. 02790 QualType castType = 02791 getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 02792 ArrayMethod->isVariadic()); 02793 castType = Context->getPointerType(castType); 02794 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 02795 cast); 02796 02797 // Don't forget the parens to enforce the proper binding. 02798 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 02799 02800 const FunctionType *FT = msgSendType->getAs<FunctionType>(); 02801 CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 02802 MsgExprs.size(), 02803 FT->getResultType(), VK_RValue, 02804 EndLoc); 02805 ReplaceStmt(Exp, CE); 02806 return CE; 02807 } 02808 02809 Stmt *RewriteModernObjC::RewriteObjCDictionaryLiteralExpr(ObjCDictionaryLiteral *Exp) { 02810 // synthesize declaration of helper functions needed in this routine. 02811 if (!SelGetUidFunctionDecl) 02812 SynthSelGetUidFunctionDecl(); 02813 // use objc_msgSend() for all. 02814 if (!MsgSendFunctionDecl) 02815 SynthMsgSendFunctionDecl(); 02816 if (!GetClassFunctionDecl) 02817 SynthGetClassFunctionDecl(); 02818 02819 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 02820 SourceLocation StartLoc = Exp->getLocStart(); 02821 SourceLocation EndLoc = Exp->getLocEnd(); 02822 02823 // Build the expression: __NSContainer_literal(int, ...).arr 02824 QualType IntQT = Context->IntTy; 02825 QualType NSDictFType = 02826 getSimpleFunctionType(Context->VoidTy, &IntQT, 1, true); 02827 std::string NSDictFName("__NSContainer_literal"); 02828 FunctionDecl *NSDictFD = SynthBlockInitFunctionDecl(NSDictFName); 02829 DeclRefExpr *NSDictDRE = 02830 new (Context) DeclRefExpr(NSDictFD, false, NSDictFType, VK_RValue, 02831 SourceLocation()); 02832 02833 SmallVector<Expr*, 16> KeyExprs; 02834 SmallVector<Expr*, 16> ValueExprs; 02835 02836 unsigned NumElements = Exp->getNumElements(); 02837 unsigned UnsignedIntSize = 02838 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 02839 Expr *count = IntegerLiteral::Create(*Context, 02840 llvm::APInt(UnsignedIntSize, NumElements), 02841 Context->UnsignedIntTy, SourceLocation()); 02842 KeyExprs.push_back(count); 02843 ValueExprs.push_back(count); 02844 for (unsigned i = 0; i < NumElements; i++) { 02845 ObjCDictionaryElement Element = Exp->getKeyValueElement(i); 02846 KeyExprs.push_back(Element.Key); 02847 ValueExprs.push_back(Element.Value); 02848 } 02849 02850 // (const id [])objects 02851 Expr *NSValueCallExpr = 02852 new (Context) CallExpr(*Context, NSDictDRE, &ValueExprs[0], ValueExprs.size(), 02853 NSDictFType, VK_LValue, SourceLocation()); 02854 02855 FieldDecl *ARRFD = FieldDecl::Create(*Context, 0, SourceLocation(), 02856 SourceLocation(), 02857 &Context->Idents.get("arr"), 02858 Context->getPointerType(Context->VoidPtrTy), 0, 02859 /*BitWidth=*/0, /*Mutable=*/true, 02860 /*HasInit=*/false); 02861 MemberExpr *DictLiteralValueME = 02862 new (Context) MemberExpr(NSValueCallExpr, false, ARRFD, 02863 SourceLocation(), 02864 ARRFD->getType(), VK_LValue, 02865 OK_Ordinary); 02866 QualType ConstIdT = Context->getObjCIdType().withConst(); 02867 CStyleCastExpr * DictValueObjects = 02868 NoTypeInfoCStyleCastExpr(Context, 02869 Context->getPointerType(ConstIdT), 02870 CK_BitCast, 02871 DictLiteralValueME); 02872 // (const id <NSCopying> [])keys 02873 Expr *NSKeyCallExpr = 02874 new (Context) CallExpr(*Context, NSDictDRE, &KeyExprs[0], KeyExprs.size(), 02875 NSDictFType, VK_LValue, SourceLocation()); 02876 02877 MemberExpr *DictLiteralKeyME = 02878 new (Context) MemberExpr(NSKeyCallExpr, false, ARRFD, 02879 SourceLocation(), 02880 ARRFD->getType(), VK_LValue, 02881 OK_Ordinary); 02882 02883 CStyleCastExpr * DictKeyObjects = 02884 NoTypeInfoCStyleCastExpr(Context, 02885 Context->getPointerType(ConstIdT), 02886 CK_BitCast, 02887 DictLiteralKeyME); 02888 02889 02890 02891 // Synthesize a call to objc_msgSend(). 02892 SmallVector<Expr*, 32> MsgExprs; 02893 SmallVector<Expr*, 4> ClsExprs; 02894 QualType argType = Context->getPointerType(Context->CharTy); 02895 QualType expType = Exp->getType(); 02896 02897 // Create a call to objc_getClass("NSArray"). It will be th 1st argument. 02898 ObjCInterfaceDecl *Class = 02899 expType->getPointeeType()->getAs<ObjCObjectType>()->getInterface(); 02900 02901 IdentifierInfo *clsName = Class->getIdentifier(); 02902 ClsExprs.push_back(StringLiteral::Create(*Context, 02903 clsName->getName(), 02904 StringLiteral::Ascii, false, 02905 argType, SourceLocation())); 02906 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 02907 &ClsExprs[0], 02908 ClsExprs.size(), 02909 StartLoc, EndLoc); 02910 MsgExprs.push_back(Cls); 02911 02912 // Create a call to sel_registerName("arrayWithObjects:count:"). 02913 // it will be the 2nd argument. 02914 SmallVector<Expr*, 4> SelExprs; 02915 ObjCMethodDecl *DictMethod = Exp->getDictWithObjectsMethod(); 02916 SelExprs.push_back(StringLiteral::Create(*Context, 02917 DictMethod->getSelector().getAsString(), 02918 StringLiteral::Ascii, false, 02919 argType, SourceLocation())); 02920 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 02921 &SelExprs[0], SelExprs.size(), 02922 StartLoc, EndLoc); 02923 MsgExprs.push_back(SelExp); 02924 02925 // (const id [])objects 02926 MsgExprs.push_back(DictValueObjects); 02927 02928 // (const id <NSCopying> [])keys 02929 MsgExprs.push_back(DictKeyObjects); 02930 02931 // (NSUInteger)cnt 02932 Expr *cnt = IntegerLiteral::Create(*Context, 02933 llvm::APInt(UnsignedIntSize, NumElements), 02934 Context->UnsignedIntTy, SourceLocation()); 02935 MsgExprs.push_back(cnt); 02936 02937 02938 SmallVector<QualType, 8> ArgTypes; 02939 ArgTypes.push_back(Context->getObjCIdType()); 02940 ArgTypes.push_back(Context->getObjCSelType()); 02941 for (ObjCMethodDecl::param_iterator PI = DictMethod->param_begin(), 02942 E = DictMethod->param_end(); PI != E; ++PI) { 02943 QualType T = (*PI)->getType(); 02944 if (const PointerType* PT = T->getAs<PointerType>()) { 02945 QualType PointeeTy = PT->getPointeeType(); 02946 convertToUnqualifiedObjCType(PointeeTy); 02947 T = Context->getPointerType(PointeeTy); 02948 } 02949 ArgTypes.push_back(T); 02950 } 02951 02952 QualType returnType = Exp->getType(); 02953 // Get the type, we will need to reference it in a couple spots. 02954 QualType msgSendType = MsgSendFlavor->getType(); 02955 02956 // Create a reference to the objc_msgSend() declaration. 02957 DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 02958 VK_LValue, SourceLocation()); 02959 02960 CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, 02961 Context->getPointerType(Context->VoidTy), 02962 CK_BitCast, DRE); 02963 02964 // Now do the "normal" pointer to function cast. 02965 QualType castType = 02966 getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 02967 DictMethod->isVariadic()); 02968 castType = Context->getPointerType(castType); 02969 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 02970 cast); 02971 02972 // Don't forget the parens to enforce the proper binding. 02973 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 02974 02975 const FunctionType *FT = msgSendType->getAs<FunctionType>(); 02976 CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 02977 MsgExprs.size(), 02978 FT->getResultType(), VK_RValue, 02979 EndLoc); 02980 ReplaceStmt(Exp, CE); 02981 return CE; 02982 } 02983 02984 // struct __rw_objc_super { 02985 // struct objc_object *object; struct objc_object *superClass; 02986 // }; 02987 QualType RewriteModernObjC::getSuperStructType() { 02988 if (!SuperStructDecl) { 02989 SuperStructDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 02990 SourceLocation(), SourceLocation(), 02991 &Context->Idents.get("__rw_objc_super")); 02992 QualType FieldTypes[2]; 02993 02994 // struct objc_object *object; 02995 FieldTypes[0] = Context->getObjCIdType(); 02996 // struct objc_object *superClass; 02997 FieldTypes[1] = Context->getObjCIdType(); 02998 02999 // Create fields 03000 for (unsigned i = 0; i < 2; ++i) { 03001 SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, 03002 SourceLocation(), 03003 SourceLocation(), 0, 03004 FieldTypes[i], 0, 03005 /*BitWidth=*/0, 03006 /*Mutable=*/false, 03007 /*HasInit=*/false)); 03008 } 03009 03010 SuperStructDecl->completeDefinition(); 03011 } 03012 return Context->getTagDeclType(SuperStructDecl); 03013 } 03014 03015 QualType RewriteModernObjC::getConstantStringStructType() { 03016 if (!ConstantStringDecl) { 03017 ConstantStringDecl = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 03018 SourceLocation(), SourceLocation(), 03019 &Context->Idents.get("__NSConstantStringImpl")); 03020 QualType FieldTypes[4]; 03021 03022 // struct objc_object *receiver; 03023 FieldTypes[0] = Context->getObjCIdType(); 03024 // int flags; 03025 FieldTypes[1] = Context->IntTy; 03026 // char *str; 03027 FieldTypes[2] = Context->getPointerType(Context->CharTy); 03028 // long length; 03029 FieldTypes[3] = Context->LongTy; 03030 03031 // Create fields 03032 for (unsigned i = 0; i < 4; ++i) { 03033 ConstantStringDecl->addDecl(FieldDecl::Create(*Context, 03034 ConstantStringDecl, 03035 SourceLocation(), 03036 SourceLocation(), 0, 03037 FieldTypes[i], 0, 03038 /*BitWidth=*/0, 03039 /*Mutable=*/true, 03040 /*HasInit=*/false)); 03041 } 03042 03043 ConstantStringDecl->completeDefinition(); 03044 } 03045 return Context->getTagDeclType(ConstantStringDecl); 03046 } 03047 03048 Stmt *RewriteModernObjC::SynthMessageExpr(ObjCMessageExpr *Exp, 03049 SourceLocation StartLoc, 03050 SourceLocation EndLoc) { 03051 if (!SelGetUidFunctionDecl) 03052 SynthSelGetUidFunctionDecl(); 03053 if (!MsgSendFunctionDecl) 03054 SynthMsgSendFunctionDecl(); 03055 if (!MsgSendSuperFunctionDecl) 03056 SynthMsgSendSuperFunctionDecl(); 03057 if (!MsgSendStretFunctionDecl) 03058 SynthMsgSendStretFunctionDecl(); 03059 if (!MsgSendSuperStretFunctionDecl) 03060 SynthMsgSendSuperStretFunctionDecl(); 03061 if (!MsgSendFpretFunctionDecl) 03062 SynthMsgSendFpretFunctionDecl(); 03063 if (!GetClassFunctionDecl) 03064 SynthGetClassFunctionDecl(); 03065 if (!GetSuperClassFunctionDecl) 03066 SynthGetSuperClassFunctionDecl(); 03067 if (!GetMetaClassFunctionDecl) 03068 SynthGetMetaClassFunctionDecl(); 03069 03070 // default to objc_msgSend(). 03071 FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; 03072 // May need to use objc_msgSend_stret() as well. 03073 FunctionDecl *MsgSendStretFlavor = 0; 03074 if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { 03075 QualType resultType = mDecl->getResultType(); 03076 if (resultType->isRecordType()) 03077 MsgSendStretFlavor = MsgSendStretFunctionDecl; 03078 else if (resultType->isRealFloatingType()) 03079 MsgSendFlavor = MsgSendFpretFunctionDecl; 03080 } 03081 03082 // Synthesize a call to objc_msgSend(). 03083 SmallVector<Expr*, 8> MsgExprs; 03084 switch (Exp->getReceiverKind()) { 03085 case ObjCMessageExpr::SuperClass: { 03086 MsgSendFlavor = MsgSendSuperFunctionDecl; 03087 if (MsgSendStretFlavor) 03088 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 03089 assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 03090 03091 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 03092 03093 SmallVector<Expr*, 4> InitExprs; 03094 03095 // set the receiver to self, the first argument to all methods. 03096 InitExprs.push_back( 03097 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 03098 CK_BitCast, 03099 new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 03100 false, 03101 Context->getObjCIdType(), 03102 VK_RValue, 03103 SourceLocation())) 03104 ); // set the 'receiver'. 03105 03106 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 03107 SmallVector<Expr*, 8> ClsExprs; 03108 QualType argType = Context->getPointerType(Context->CharTy); 03109 ClsExprs.push_back(StringLiteral::Create(*Context, 03110 ClassDecl->getIdentifier()->getName(), 03111 StringLiteral::Ascii, false, 03112 argType, SourceLocation())); 03113 // (Class)objc_getClass("CurrentClass") 03114 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl, 03115 &ClsExprs[0], 03116 ClsExprs.size(), 03117 StartLoc, 03118 EndLoc); 03119 ClsExprs.clear(); 03120 ClsExprs.push_back(Cls); 03121 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 03122 &ClsExprs[0], ClsExprs.size(), 03123 StartLoc, EndLoc); 03124 03125 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 03126 // To turn off a warning, type-cast to 'id' 03127 InitExprs.push_back( // set 'super class', using class_getSuperclass(). 03128 NoTypeInfoCStyleCastExpr(Context, 03129 Context->getObjCIdType(), 03130 CK_BitCast, Cls)); 03131 // struct __rw_objc_super 03132 QualType superType = getSuperStructType(); 03133 Expr *SuperRep; 03134 03135 if (LangOpts.MicrosoftExt) { 03136 SynthSuperContructorFunctionDecl(); 03137 // Simulate a contructor call... 03138 DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, 03139 false, superType, VK_LValue, 03140 SourceLocation()); 03141 SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], 03142 InitExprs.size(), 03143 superType, VK_LValue, 03144 SourceLocation()); 03145 // The code for super is a little tricky to prevent collision with 03146 // the structure definition in the header. The rewriter has it's own 03147 // internal definition (__rw_objc_super) that is uses. This is why 03148 // we need the cast below. For example: 03149 // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 03150 // 03151 SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 03152 Context->getPointerType(SuperRep->getType()), 03153 VK_RValue, OK_Ordinary, 03154 SourceLocation()); 03155 SuperRep = NoTypeInfoCStyleCastExpr(Context, 03156 Context->getPointerType(superType), 03157 CK_BitCast, SuperRep); 03158 } else { 03159 // (struct __rw_objc_super) { <exprs from above> } 03160 InitListExpr *ILE = 03161 new (Context) InitListExpr(*Context, SourceLocation(), 03162 &InitExprs[0], InitExprs.size(), 03163 SourceLocation()); 03164 TypeSourceInfo *superTInfo 03165 = Context->getTrivialTypeSourceInfo(superType); 03166 SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 03167 superType, VK_LValue, 03168 ILE, false); 03169 // struct __rw_objc_super * 03170 SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 03171 Context->getPointerType(SuperRep->getType()), 03172 VK_RValue, OK_Ordinary, 03173 SourceLocation()); 03174 } 03175 MsgExprs.push_back(SuperRep); 03176 break; 03177 } 03178 03179 case ObjCMessageExpr::Class: { 03180 SmallVector<Expr*, 8> ClsExprs; 03181 QualType argType = Context->getPointerType(Context->CharTy); 03182 ObjCInterfaceDecl *Class 03183 = Exp->getClassReceiver()->getAs<ObjCObjectType>()->getInterface(); 03184 IdentifierInfo *clsName = Class->getIdentifier(); 03185 ClsExprs.push_back(StringLiteral::Create(*Context, 03186 clsName->getName(), 03187 StringLiteral::Ascii, false, 03188 argType, SourceLocation())); 03189 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 03190 &ClsExprs[0], 03191 ClsExprs.size(), 03192 StartLoc, EndLoc); 03193 CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, 03194 Context->getObjCIdType(), 03195 CK_BitCast, Cls); 03196 MsgExprs.push_back(ArgExpr); 03197 break; 03198 } 03199 03200 case ObjCMessageExpr::SuperInstance:{ 03201 MsgSendFlavor = MsgSendSuperFunctionDecl; 03202 if (MsgSendStretFlavor) 03203 MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; 03204 assert(MsgSendFlavor && "MsgSendFlavor is NULL!"); 03205 ObjCInterfaceDecl *ClassDecl = CurMethodDef->getClassInterface(); 03206 SmallVector<Expr*, 4> InitExprs; 03207 03208 InitExprs.push_back( 03209 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 03210 CK_BitCast, 03211 new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), 03212 false, 03213 Context->getObjCIdType(), 03214 VK_RValue, SourceLocation())) 03215 ); // set the 'receiver'. 03216 03217 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 03218 SmallVector<Expr*, 8> ClsExprs; 03219 QualType argType = Context->getPointerType(Context->CharTy); 03220 ClsExprs.push_back(StringLiteral::Create(*Context, 03221 ClassDecl->getIdentifier()->getName(), 03222 StringLiteral::Ascii, false, argType, 03223 SourceLocation())); 03224 // (Class)objc_getClass("CurrentClass") 03225 CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl, 03226 &ClsExprs[0], 03227 ClsExprs.size(), 03228 StartLoc, EndLoc); 03229 ClsExprs.clear(); 03230 ClsExprs.push_back(Cls); 03231 Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, 03232 &ClsExprs[0], ClsExprs.size(), 03233 StartLoc, EndLoc); 03234 03235 // (id)class_getSuperclass((Class)objc_getClass("CurrentClass")) 03236 // To turn off a warning, type-cast to 'id' 03237 InitExprs.push_back( 03238 // set 'super class', using class_getSuperclass(). 03239 NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 03240 CK_BitCast, Cls)); 03241 // struct __rw_objc_super 03242 QualType superType = getSuperStructType(); 03243 Expr *SuperRep; 03244 03245 if (LangOpts.MicrosoftExt) { 03246 SynthSuperContructorFunctionDecl(); 03247 // Simulate a contructor call... 03248 DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, 03249 false, superType, VK_LValue, 03250 SourceLocation()); 03251 SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], 03252 InitExprs.size(), 03253 superType, VK_LValue, SourceLocation()); 03254 // The code for super is a little tricky to prevent collision with 03255 // the structure definition in the header. The rewriter has it's own 03256 // internal definition (__rw_objc_super) that is uses. This is why 03257 // we need the cast below. For example: 03258 // (struct __rw_objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER")) 03259 // 03260 SuperRep = new (Context) UnaryOperator(SuperRep, UO_AddrOf, 03261 Context->getPointerType(SuperRep->getType()), 03262 VK_RValue, OK_Ordinary, 03263 SourceLocation()); 03264 SuperRep = NoTypeInfoCStyleCastExpr(Context, 03265 Context->getPointerType(superType), 03266 CK_BitCast, SuperRep); 03267 } else { 03268 // (struct __rw_objc_super) { <exprs from above> } 03269 InitListExpr *ILE = 03270 new (Context) InitListExpr(*Context, SourceLocation(), 03271 &InitExprs[0], InitExprs.size(), 03272 SourceLocation()); 03273 TypeSourceInfo *superTInfo 03274 = Context->getTrivialTypeSourceInfo(superType); 03275 SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo, 03276 superType, VK_RValue, ILE, 03277 false); 03278 } 03279 MsgExprs.push_back(SuperRep); 03280 break; 03281 } 03282 03283 case ObjCMessageExpr::Instance: { 03284 // Remove all type-casts because it may contain objc-style types; e.g. 03285 // Foo<Proto> *. 03286 Expr *recExpr = Exp->getInstanceReceiver(); 03287 while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr)) 03288 recExpr = CE->getSubExpr(); 03289 CastKind CK = recExpr->getType()->isObjCObjectPointerType() 03290 ? CK_BitCast : recExpr->getType()->isBlockPointerType() 03291 ? CK_BlockPointerToObjCPointerCast 03292 : CK_CPointerToObjCPointerCast; 03293 03294 recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 03295 CK, recExpr); 03296 MsgExprs.push_back(recExpr); 03297 break; 03298 } 03299 } 03300 03301 // Create a call to sel_registerName("selName"), it will be the 2nd argument. 03302 SmallVector<Expr*, 8> SelExprs; 03303 QualType argType = Context->getPointerType(Context->CharTy); 03304 SelExprs.push_back(StringLiteral::Create(*Context, 03305 Exp->getSelector().getAsString(), 03306 StringLiteral::Ascii, false, 03307 argType, SourceLocation())); 03308 CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl, 03309 &SelExprs[0], SelExprs.size(), 03310 StartLoc, 03311 EndLoc); 03312 MsgExprs.push_back(SelExp); 03313 03314 // Now push any user supplied arguments. 03315 for (unsigned i = 0; i < Exp->getNumArgs(); i++) { 03316 Expr *userExpr = Exp->getArg(i); 03317 // Make all implicit casts explicit...ICE comes in handy:-) 03318 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) { 03319 // Reuse the ICE type, it is exactly what the doctor ordered. 03320 QualType type = ICE->getType(); 03321 if (needToScanForQualifiers(type)) 03322 type = Context->getObjCIdType(); 03323 // Make sure we convert "type (^)(...)" to "type (*)(...)". 03324 (void)convertBlockPointerToFunctionPointer(type); 03325 const Expr *SubExpr = ICE->IgnoreParenImpCasts(); 03326 CastKind CK; 03327 if (SubExpr->getType()->isIntegralType(*Context) && 03328 type->isBooleanType()) { 03329 CK = CK_IntegralToBoolean; 03330 } else if (type->isObjCObjectPointerType()) { 03331 if (SubExpr->getType()->isBlockPointerType()) { 03332 CK = CK_BlockPointerToObjCPointerCast; 03333 } else if (SubExpr->getType()->isPointerType()) { 03334 CK = CK_CPointerToObjCPointerCast; 03335 } else { 03336 CK = CK_BitCast; 03337 } 03338 } else { 03339 CK = CK_BitCast; 03340 } 03341 03342 userExpr = NoTypeInfoCStyleCastExpr(Context, type, CK, userExpr); 03343 } 03344 // Make id<P...> cast into an 'id' cast. 03345 else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) { 03346 if (CE->getType()->isObjCQualifiedIdType()) { 03347 while ((CE = dyn_cast<CStyleCastExpr>(userExpr))) 03348 userExpr = CE->getSubExpr(); 03349 CastKind CK; 03350 if (userExpr->getType()->isIntegralType(*Context)) { 03351 CK = CK_IntegralToPointer; 03352 } else if (userExpr->getType()->isBlockPointerType()) { 03353 CK = CK_BlockPointerToObjCPointerCast; 03354 } else if (userExpr->getType()->isPointerType()) { 03355 CK = CK_CPointerToObjCPointerCast; 03356 } else { 03357 CK = CK_BitCast; 03358 } 03359 userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), 03360 CK, userExpr); 03361 } 03362 } 03363 MsgExprs.push_back(userExpr); 03364 // We've transferred the ownership to MsgExprs. For now, we *don't* null 03365 // out the argument in the original expression (since we aren't deleting 03366 // the ObjCMessageExpr). See RewritePropertyOrImplicitSetter() usage for more info. 03367 //Exp->setArg(i, 0); 03368 } 03369 // Generate the funky cast. 03370 CastExpr *cast; 03371 SmallVector<QualType, 8> ArgTypes; 03372 QualType returnType; 03373 03374 // Push 'id' and 'SEL', the 2 implicit arguments. 03375 if (MsgSendFlavor == MsgSendSuperFunctionDecl) 03376 ArgTypes.push_back(Context->getPointerType(getSuperStructType())); 03377 else 03378 ArgTypes.push_back(Context->getObjCIdType()); 03379 ArgTypes.push_back(Context->getObjCSelType()); 03380 if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { 03381 // Push any user argument types. 03382 for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(), 03383 E = OMD->param_end(); PI != E; ++PI) { 03384 QualType t = (*PI)->getType()->isObjCQualifiedIdType() 03385 ? Context->getObjCIdType() 03386 : (*PI)->getType(); 03387 // Make sure we convert "t (^)(...)" to "t (*)(...)". 03388 (void)convertBlockPointerToFunctionPointer(t); 03389 ArgTypes.push_back(t); 03390 } 03391 returnType = Exp->getType(); 03392 convertToUnqualifiedObjCType(returnType); 03393 (void)convertBlockPointerToFunctionPointer(returnType); 03394 } else { 03395 returnType = Context->getObjCIdType(); 03396 } 03397 // Get the type, we will need to reference it in a couple spots. 03398 QualType msgSendType = MsgSendFlavor->getType(); 03399 03400 // Create a reference to the objc_msgSend() declaration. 03401 DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, 03402 VK_LValue, SourceLocation()); 03403 03404 // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). 03405 // If we don't do this cast, we get the following bizarre warning/note: 03406 // xx.m:13: warning: function called through a non-compatible type 03407 // xx.m:13: note: if this code is reached, the program will abort 03408 cast = NoTypeInfoCStyleCastExpr(Context, 03409 Context->getPointerType(Context->VoidTy), 03410 CK_BitCast, DRE); 03411 03412 // Now do the "normal" pointer to function cast. 03413 QualType castType = 03414 getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 03415 // If we don't have a method decl, force a variadic cast. 03416 Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true); 03417 castType = Context->getPointerType(castType); 03418 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 03419 cast); 03420 03421 // Don't forget the parens to enforce the proper binding. 03422 ParenExpr *PE = new (Context) ParenExpr(StartLoc, EndLoc, cast); 03423 03424 const FunctionType *FT = msgSendType->getAs<FunctionType>(); 03425 CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 03426 MsgExprs.size(), 03427 FT->getResultType(), VK_RValue, 03428 EndLoc); 03429 Stmt *ReplacingStmt = CE; 03430 if (MsgSendStretFlavor) { 03431 // We have the method which returns a struct/union. Must also generate 03432 // call to objc_msgSend_stret and hang both varieties on a conditional 03433 // expression which dictate which one to envoke depending on size of 03434 // method's return type. 03435 03436 // Create a reference to the objc_msgSend_stret() declaration. 03437 DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, 03438 false, msgSendType, 03439 VK_LValue, SourceLocation()); 03440 // Need to cast objc_msgSend_stret to "void *" (see above comment). 03441 cast = NoTypeInfoCStyleCastExpr(Context, 03442 Context->getPointerType(Context->VoidTy), 03443 CK_BitCast, STDRE); 03444 // Now do the "normal" pointer to function cast. 03445 castType = getSimpleFunctionType(returnType, &ArgTypes[0], ArgTypes.size(), 03446 Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false); 03447 castType = Context->getPointerType(castType); 03448 cast = NoTypeInfoCStyleCastExpr(Context, castType, CK_BitCast, 03449 cast); 03450 03451 // Don't forget the parens to enforce the proper binding. 03452 PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast); 03453 03454 FT = msgSendType->getAs<FunctionType>(); 03455 CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0], 03456 MsgExprs.size(), 03457 FT->getResultType(), VK_RValue, 03458 SourceLocation()); 03459 03460 // Build sizeof(returnType) 03461 UnaryExprOrTypeTraitExpr *sizeofExpr = 03462 new (Context) UnaryExprOrTypeTraitExpr(UETT_SizeOf, 03463 Context->getTrivialTypeSourceInfo(returnType), 03464 Context->getSizeType(), SourceLocation(), 03465 SourceLocation()); 03466 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 03467 // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases. 03468 // For X86 it is more complicated and some kind of target specific routine 03469 // is needed to decide what to do. 03470 unsigned IntSize = 03471 static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 03472 IntegerLiteral *limit = IntegerLiteral::Create(*Context, 03473 llvm::APInt(IntSize, 8), 03474 Context->IntTy, 03475 SourceLocation()); 03476 BinaryOperator *lessThanExpr = 03477 new (Context) BinaryOperator(sizeofExpr, limit, BO_LE, Context->IntTy, 03478 VK_RValue, OK_Ordinary, SourceLocation()); 03479 // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...)) 03480 ConditionalOperator *CondExpr = 03481 new (Context) ConditionalOperator(lessThanExpr, 03482 SourceLocation(), CE, 03483 SourceLocation(), STCE, 03484 returnType, VK_RValue, OK_Ordinary); 03485 ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 03486 CondExpr); 03487 } 03488 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 03489 return ReplacingStmt; 03490 } 03491 03492 Stmt *RewriteModernObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { 03493 Stmt *ReplacingStmt = SynthMessageExpr(Exp, Exp->getLocStart(), 03494 Exp->getLocEnd()); 03495 03496 // Now do the actual rewrite. 03497 ReplaceStmt(Exp, ReplacingStmt); 03498 03499 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 03500 return ReplacingStmt; 03501 } 03502 03503 // typedef struct objc_object Protocol; 03504 QualType RewriteModernObjC::getProtocolType() { 03505 if (!ProtocolTypeDecl) { 03506 TypeSourceInfo *TInfo 03507 = Context->getTrivialTypeSourceInfo(Context->getObjCIdType()); 03508 ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, 03509 SourceLocation(), SourceLocation(), 03510 &Context->Idents.get("Protocol"), 03511 TInfo); 03512 } 03513 return Context->getTypeDeclType(ProtocolTypeDecl); 03514 } 03515 03516 /// RewriteObjCProtocolExpr - Rewrite a protocol expression into 03517 /// a synthesized/forward data reference (to the protocol's metadata). 03518 /// The forward references (and metadata) are generated in 03519 /// RewriteModernObjC::HandleTranslationUnit(). 03520 Stmt *RewriteModernObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { 03521 std::string Name = "_OBJC_PROTOCOL_REFERENCE_$_" + 03522 Exp->getProtocol()->getNameAsString(); 03523 IdentifierInfo *ID = &Context->Idents.get(Name); 03524 VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 03525 SourceLocation(), ID, getProtocolType(), 0, 03526 SC_Extern, SC_None); 03527 DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(), 03528 VK_LValue, SourceLocation()); 03529 Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, 03530 Context->getPointerType(DRE->getType()), 03531 VK_RValue, OK_Ordinary, SourceLocation()); 03532 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(), 03533 CK_BitCast, 03534 DerefExpr); 03535 ReplaceStmt(Exp, castExpr); 03536 ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl()); 03537 // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. 03538 return castExpr; 03539 03540 } 03541 03542 bool RewriteModernObjC::BufferContainsPPDirectives(const char *startBuf, 03543 const char *endBuf) { 03544 while (startBuf < endBuf) { 03545 if (*startBuf == '#') { 03546 // Skip whitespace. 03547 for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf) 03548 ; 03549 if (!strncmp(startBuf, "if", strlen("if")) || 03550 !strncmp(startBuf, "ifdef", strlen("ifdef")) || 03551 !strncmp(startBuf, "ifndef", strlen("ifndef")) || 03552 !strncmp(startBuf, "define", strlen("define")) || 03553 !strncmp(startBuf, "undef", strlen("undef")) || 03554 !strncmp(startBuf, "else", strlen("else")) || 03555 !strncmp(startBuf, "elif", strlen("elif")) || 03556 !strncmp(startBuf, "endif", strlen("endif")) || 03557 !strncmp(startBuf, "pragma", strlen("pragma")) || 03558 !strncmp(startBuf, "include", strlen("include")) || 03559 !strncmp(startBuf, "import", strlen("import")) || 03560 !strncmp(startBuf, "include_next", strlen("include_next"))) 03561 return true; 03562 } 03563 startBuf++; 03564 } 03565 return false; 03566 } 03567 03568 /// IsTagDefinedInsideClass - This routine checks that a named tagged type 03569 /// is defined inside an objective-c class. If so, it returns true. 03570 bool RewriteModernObjC::IsTagDefinedInsideClass(ObjCContainerDecl *IDecl, 03571 TagDecl *Tag, 03572 bool &IsNamedDefinition) { 03573 if (!IDecl) 03574 return false; 03575 SourceLocation TagLocation; 03576 if (RecordDecl *RD = dyn_cast<RecordDecl>(Tag)) { 03577 RD = RD->getDefinition(); 03578 if (!RD || !RD->getDeclName().getAsIdentifierInfo()) 03579 return false; 03580 IsNamedDefinition = true; 03581 TagLocation = RD->getLocation(); 03582 return Context->getSourceManager().isBeforeInTranslationUnit( 03583 IDecl->getLocation(), TagLocation); 03584 } 03585 if (EnumDecl *ED = dyn_cast<EnumDecl>(Tag)) { 03586 if (!ED || !ED->getDeclName().getAsIdentifierInfo()) 03587 return false; 03588 IsNamedDefinition = true; 03589 TagLocation = ED->getLocation(); 03590 return Context->getSourceManager().isBeforeInTranslationUnit( 03591 IDecl->getLocation(), TagLocation); 03592 03593 } 03594 return false; 03595 } 03596 03597 /// RewriteObjCFieldDeclType - This routine rewrites a type into the buffer. 03598 /// It handles elaborated types, as well as enum types in the process. 03599 bool RewriteModernObjC::RewriteObjCFieldDeclType(QualType &Type, 03600 std::string &Result) { 03601 if (isa<TypedefType>(Type)) { 03602 Result += "\t"; 03603 return false; 03604 } 03605 03606 if (Type->isArrayType()) { 03607 QualType ElemTy = Context->getBaseElementType(Type); 03608 return RewriteObjCFieldDeclType(ElemTy, Result); 03609 } 03610 else if (Type->isRecordType()) { 03611 RecordDecl *RD = Type->getAs<RecordType>()->getDecl(); 03612 if (RD->isCompleteDefinition()) { 03613 if (RD->isStruct()) 03614 Result += "\n\tstruct "; 03615 else if (RD->isUnion()) 03616 Result += "\n\tunion "; 03617 else 03618 assert(false && "class not allowed as an ivar type"); 03619 03620 Result += RD->getName(); 03621 if (GlobalDefinedTags.count(RD)) { 03622 // struct/union is defined globally, use it. 03623 Result += " "; 03624 return true; 03625 } 03626 Result += " {\n"; 03627 for (RecordDecl::field_iterator i = RD->field_begin(), 03628 e = RD->field_end(); i != e; ++i) { 03629 FieldDecl *FD = &*i; 03630 RewriteObjCFieldDecl(FD, Result); 03631 } 03632 Result += "\t} "; 03633 return true; 03634 } 03635 } 03636 else if (Type->isEnumeralType()) { 03637 EnumDecl *ED = Type->getAs<EnumType>()->getDecl(); 03638 if (ED->isCompleteDefinition()) { 03639 Result += "\n\tenum "; 03640 Result += ED->getName(); 03641 if (GlobalDefinedTags.count(ED)) { 03642 // Enum is globall defined, use it. 03643 Result += " "; 03644 return true; 03645 } 03646 03647 Result += " {\n"; 03648 for (EnumDecl::enumerator_iterator EC = ED->enumerator_begin(), 03649 ECEnd = ED->enumerator_end(); EC != ECEnd; ++EC) { 03650 Result += "\t"; Result += EC->getName(); Result += " = "; 03651 llvm::APSInt Val = EC->getInitVal(); 03652 Result += Val.toString(10); 03653 Result += ",\n"; 03654 } 03655 Result += "\t} "; 03656 return true; 03657 } 03658 } 03659 03660 Result += "\t"; 03661 convertObjCTypeToCStyleType(Type); 03662 return false; 03663 } 03664 03665 03666 /// RewriteObjCFieldDecl - This routine rewrites a field into the buffer. 03667 /// It handles elaborated types, as well as enum types in the process. 03668 void RewriteModernObjC::RewriteObjCFieldDecl(FieldDecl *fieldDecl, 03669 std::string &Result) { 03670 QualType Type = fieldDecl->getType(); 03671 std::string Name = fieldDecl->getNameAsString(); 03672 03673 bool EleboratedType = RewriteObjCFieldDeclType(Type, Result); 03674 if (!EleboratedType) 03675 Type.getAsStringInternal(Name, Context->getPrintingPolicy()); 03676 Result += Name; 03677 if (fieldDecl->isBitField()) { 03678 Result += " : "; Result += utostr(fieldDecl->getBitWidthValue(*Context)); 03679 } 03680 else if (EleboratedType && Type->isArrayType()) { 03681 CanQualType CType = Context->getCanonicalType(Type); 03682 while (isa<ArrayType>(CType)) { 03683 if (const ConstantArrayType *CAT = Context->getAsConstantArrayType(CType)) { 03684 Result += "["; 03685 llvm::APInt Dim = CAT->getSize(); 03686 Result += utostr(Dim.getZExtValue()); 03687 Result += "]"; 03688 } 03689 CType = CType->getAs<ArrayType>()->getElementType(); 03690 } 03691 } 03692 03693 Result += ";\n"; 03694 } 03695 03696 /// RewriteLocallyDefinedNamedAggregates - This routine rewrites locally defined 03697 /// named aggregate types into the input buffer. 03698 void RewriteModernObjC::RewriteLocallyDefinedNamedAggregates(FieldDecl *fieldDecl, 03699 std::string &Result) { 03700 QualType Type = fieldDecl->getType(); 03701 if (isa<TypedefType>(Type)) 03702 return; 03703 if (Type->isArrayType()) 03704 Type = Context->getBaseElementType(Type); 03705 ObjCContainerDecl *IDecl = 03706 dyn_cast<ObjCContainerDecl>(fieldDecl->getDeclContext()); 03707 03708 TagDecl *TD = 0; 03709 if (Type->isRecordType()) { 03710 TD = Type->getAs<RecordType>()->getDecl(); 03711 } 03712 else if (Type->isEnumeralType()) { 03713 TD = Type->getAs<EnumType>()->getDecl(); 03714 } 03715 03716 if (TD) { 03717 if (GlobalDefinedTags.count(TD)) 03718 return; 03719 03720 bool IsNamedDefinition = false; 03721 if (IsTagDefinedInsideClass(IDecl, TD, IsNamedDefinition)) { 03722 RewriteObjCFieldDeclType(Type, Result); 03723 Result += ";"; 03724 } 03725 if (IsNamedDefinition) 03726 GlobalDefinedTags.insert(TD); 03727 } 03728 03729 } 03730 03731 /// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to 03732 /// an objective-c class with ivars. 03733 void RewriteModernObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, 03734 std::string &Result) { 03735 assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); 03736 assert(CDecl->getName() != "" && 03737 "Name missing in SynthesizeObjCInternalStruct"); 03738 ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); 03739 SmallVector<ObjCIvarDecl *, 8> IVars; 03740 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 03741 IVD; IVD = IVD->getNextIvar()) 03742 IVars.push_back(IVD); 03743 03744 SourceLocation LocStart = CDecl->getLocStart(); 03745 SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc(); 03746 03747 const char *startBuf = SM->getCharacterData(LocStart); 03748 const char *endBuf = SM->getCharacterData(LocEnd); 03749 03750 // If no ivars and no root or if its root, directly or indirectly, 03751 // have no ivars (thus not synthesized) then no need to synthesize this class. 03752 if ((!CDecl->isThisDeclarationADefinition() || IVars.size() == 0) && 03753 (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { 03754 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 03755 ReplaceText(LocStart, endBuf-startBuf, Result); 03756 return; 03757 } 03758 03759 // Insert named struct/union definitions inside class to 03760 // outer scope. This follows semantics of locally defined 03761 // struct/unions in objective-c classes. 03762 for (unsigned i = 0, e = IVars.size(); i < e; i++) 03763 RewriteLocallyDefinedNamedAggregates(IVars[i], Result); 03764 03765 Result += "\nstruct "; 03766 Result += CDecl->getNameAsString(); 03767 Result += "_IMPL {\n"; 03768 03769 if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { 03770 Result += "\tstruct "; Result += RCDecl->getNameAsString(); 03771 Result += "_IMPL "; Result += RCDecl->getNameAsString(); 03772 Result += "_IVARS;\n"; 03773 } 03774 03775 for (unsigned i = 0, e = IVars.size(); i < e; i++) 03776 RewriteObjCFieldDecl(IVars[i], Result); 03777 03778 Result += "};\n"; 03779 endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); 03780 ReplaceText(LocStart, endBuf-startBuf, Result); 03781 // Mark this struct as having been generated. 03782 if (!ObjCSynthesizedStructs.insert(CDecl)) 03783 llvm_unreachable("struct already synthesize- RewriteObjCInternalStruct"); 03784 } 03785 03786 /// RewriteIvarOffsetSymbols - Rewrite ivar offset symbols of those ivars which 03787 /// have been referenced in an ivar access expression. 03788 void RewriteModernObjC::RewriteIvarOffsetSymbols(ObjCInterfaceDecl *CDecl, 03789 std::string &Result) { 03790 // write out ivar offset symbols which have been referenced in an ivar 03791 // access expression. 03792 llvm::SmallPtrSet<ObjCIvarDecl *, 8> Ivars = ReferencedIvars[CDecl]; 03793 if (Ivars.empty()) 03794 return; 03795 for (llvm::SmallPtrSet<ObjCIvarDecl *, 8>::iterator i = Ivars.begin(), 03796 e = Ivars.end(); i != e; i++) { 03797 ObjCIvarDecl *IvarDecl = (*i); 03798 Result += "\n"; 03799 if (LangOpts.MicrosoftExt) 03800 Result += "__declspec(allocate(\".objc_ivar$B\")) "; 03801 Result += "extern \"C\" "; 03802 if (LangOpts.MicrosoftExt && 03803 IvarDecl->getAccessControl() != ObjCIvarDecl::Private && 03804 IvarDecl->getAccessControl() != ObjCIvarDecl::Package) 03805 Result += "__declspec(dllimport) "; 03806 03807 Result += "unsigned long "; 03808 WriteInternalIvarName(CDecl, IvarDecl, Result); 03809 Result += ";"; 03810 } 03811 } 03812 03813 //===----------------------------------------------------------------------===// 03814 // Meta Data Emission 03815 //===----------------------------------------------------------------------===// 03816 03817 03818 /// RewriteImplementations - This routine rewrites all method implementations 03819 /// and emits meta-data. 03820 03821 void RewriteModernObjC::RewriteImplementations() { 03822 int ClsDefCount = ClassImplementation.size(); 03823 int CatDefCount = CategoryImplementation.size(); 03824 03825 // Rewrite implemented methods 03826 for (int i = 0; i < ClsDefCount; i++) { 03827 ObjCImplementationDecl *OIMP = ClassImplementation[i]; 03828 ObjCInterfaceDecl *CDecl = OIMP->getClassInterface(); 03829 if (CDecl->isImplicitInterfaceDecl()) 03830 assert(false && 03831 "Legacy implicit interface rewriting not supported in moder abi"); 03832 RewriteImplementationDecl(OIMP); 03833 } 03834 03835 for (int i = 0; i < CatDefCount; i++) { 03836 ObjCCategoryImplDecl *CIMP = CategoryImplementation[i]; 03837 ObjCInterfaceDecl *CDecl = CIMP->getClassInterface(); 03838 if (CDecl->isImplicitInterfaceDecl()) 03839 assert(false && 03840 "Legacy implicit interface rewriting not supported in moder abi"); 03841 RewriteImplementationDecl(CIMP); 03842 } 03843 } 03844 03845 void RewriteModernObjC::RewriteByRefString(std::string &ResultStr, 03846 const std::string &Name, 03847 ValueDecl *VD, bool def) { 03848 assert(BlockByRefDeclNo.count(VD) && 03849 "RewriteByRefString: ByRef decl missing"); 03850 if (def) 03851 ResultStr += "struct "; 03852 ResultStr += "__Block_byref_" + Name + 03853 "_" + utostr(BlockByRefDeclNo[VD]) ; 03854 } 03855 03856 static bool HasLocalVariableExternalStorage(ValueDecl *VD) { 03857 if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 03858 return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage()); 03859 return false; 03860 } 03861 03862 std::string RewriteModernObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, 03863 StringRef funcName, 03864 std::string Tag) { 03865 const FunctionType *AFT = CE->getFunctionType(); 03866 QualType RT = AFT->getResultType(); 03867 std::string StructRef = "struct " + Tag; 03868 std::string S = "static " + RT.getAsString(Context->getPrintingPolicy()) + " __" + 03869 funcName.str() + "_block_func_" + utostr(i); 03870 03871 BlockDecl *BD = CE->getBlockDecl(); 03872 03873 if (isa<FunctionNoProtoType>(AFT)) { 03874 // No user-supplied arguments. Still need to pass in a pointer to the 03875 // block (to reference imported block decl refs). 03876 S += "(" + StructRef + " *__cself)"; 03877 } else if (BD->param_empty()) { 03878 S += "(" + StructRef + " *__cself)"; 03879 } else { 03880 const FunctionProtoType *FT = cast<FunctionProtoType>(AFT); 03881 assert(FT && "SynthesizeBlockFunc: No function proto"); 03882 S += '('; 03883 // first add the implicit argument. 03884 S += StructRef + " *__cself, "; 03885 std::string ParamStr; 03886 for (BlockDecl::param_iterator AI = BD->param_begin(), 03887 E = BD->param_end(); AI != E; ++AI) { 03888 if (AI != BD->param_begin()) S += ", "; 03889 ParamStr = (*AI)->getNameAsString(); 03890 QualType QT = (*AI)->getType(); 03891 (void)convertBlockPointerToFunctionPointer(QT); 03892 QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); 03893 S += ParamStr; 03894 } 03895 if (FT->isVariadic()) { 03896 if (!BD->param_empty()) S += ", "; 03897 S += "..."; 03898 } 03899 S += ')'; 03900 } 03901 S += " {\n"; 03902 03903 // Create local declarations to avoid rewriting all closure decl ref exprs. 03904 // First, emit a declaration for all "by ref" decls. 03905 for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 03906 E = BlockByRefDecls.end(); I != E; ++I) { 03907 S += " "; 03908 std::string Name = (*I)->getNameAsString(); 03909 std::string TypeString; 03910 RewriteByRefString(TypeString, Name, (*I)); 03911 TypeString += " *"; 03912 Name = TypeString + Name; 03913 S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; 03914 } 03915 // Next, emit a declaration for all "by copy" declarations. 03916 for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 03917 E = BlockByCopyDecls.end(); I != E; ++I) { 03918 S += " "; 03919 // Handle nested closure invocation. For example: 03920 // 03921 // void (^myImportedClosure)(void); 03922 // myImportedClosure = ^(void) { setGlobalInt(x + y); }; 03923 // 03924 // void (^anotherClosure)(void); 03925 // anotherClosure = ^(void) { 03926 // myImportedClosure(); // import and invoke the closure 03927 // }; 03928 // 03929 if (isTopLevelBlockPointerType((*I)->getType())) { 03930 RewriteBlockPointerTypeVariable(S, (*I)); 03931 S += " = ("; 03932 RewriteBlockPointerType(S, (*I)->getType()); 03933 S += ")"; 03934 S += "__cself->" + (*I)->getNameAsString() + "; // bound by copy\n"; 03935 } 03936 else { 03937 std::string Name = (*I)->getNameAsString(); 03938 QualType QT = (*I)->getType(); 03939 if (HasLocalVariableExternalStorage(*I)) 03940 QT = Context->getPointerType(QT); 03941 QT.getAsStringInternal(Name, Context->getPrintingPolicy()); 03942 S += Name + " = __cself->" + 03943 (*I)->getNameAsString() + "; // bound by copy\n"; 03944 } 03945 } 03946 std::string RewrittenStr = RewrittenBlockExprs[CE]; 03947 const char *cstr = RewrittenStr.c_str(); 03948 while (*cstr++ != '{') ; 03949 S += cstr; 03950 S += "\n"; 03951 return S; 03952 } 03953 03954 std::string RewriteModernObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, 03955 StringRef funcName, 03956 std::string Tag) { 03957 std::string StructRef = "struct " + Tag; 03958 std::string S = "static void __"; 03959 03960 S += funcName; 03961 S += "_block_copy_" + utostr(i); 03962 S += "(" + StructRef; 03963 S += "*dst, " + StructRef; 03964 S += "*src) {"; 03965 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 03966 E = ImportedBlockDecls.end(); I != E; ++I) { 03967 ValueDecl *VD = (*I); 03968 S += "_Block_object_assign((void*)&dst->"; 03969 S += (*I)->getNameAsString(); 03970 S += ", (void*)src->"; 03971 S += (*I)->getNameAsString(); 03972 if (BlockByRefDeclsPtrSet.count((*I))) 03973 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 03974 else if (VD->getType()->isBlockPointerType()) 03975 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 03976 else 03977 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 03978 } 03979 S += "}\n"; 03980 03981 S += "\nstatic void __"; 03982 S += funcName; 03983 S += "_block_dispose_" + utostr(i); 03984 S += "(" + StructRef; 03985 S += "*src) {"; 03986 for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = ImportedBlockDecls.begin(), 03987 E = ImportedBlockDecls.end(); I != E; ++I) { 03988 ValueDecl *VD = (*I); 03989 S += "_Block_object_dispose((void*)src->"; 03990 S += (*I)->getNameAsString(); 03991 if (BlockByRefDeclsPtrSet.count((*I))) 03992 S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; 03993 else if (VD->getType()->isBlockPointerType()) 03994 S += ", " + utostr(BLOCK_FIELD_IS_BLOCK) + "/*BLOCK_FIELD_IS_BLOCK*/);"; 03995 else 03996 S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; 03997 } 03998 S += "}\n"; 03999 return S; 04000 } 04001 04002 std::string RewriteModernObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, 04003 std::string Desc) { 04004 std::string S = "\nstruct " + Tag; 04005 std::string Constructor = " " + Tag; 04006 04007 S += " {\n struct __block_impl impl;\n"; 04008 S += " struct " + Desc; 04009 S += "* Desc;\n"; 04010 04011 Constructor += "(void *fp, "; // Invoke function pointer. 04012 Constructor += "struct " + Desc; // Descriptor pointer. 04013 Constructor += " *desc"; 04014 04015 if (BlockDeclRefs.size()) { 04016 // Output all "by copy" declarations. 04017 for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 04018 E = BlockByCopyDecls.end(); I != E; ++I) { 04019 S += " "; 04020 std::string FieldName = (*I)->getNameAsString(); 04021 std::string ArgName = "_" + FieldName; 04022 // Handle nested closure invocation. For example: 04023 // 04024 // void (^myImportedBlock)(void); 04025 // myImportedBlock = ^(void) { setGlobalInt(x + y); }; 04026 // 04027 // void (^anotherBlock)(void); 04028 // anotherBlock = ^(void) { 04029 // myImportedBlock(); // import and invoke the closure 04030 // }; 04031 // 04032 if (isTopLevelBlockPointerType((*I)->getType())) { 04033 S += "struct __block_impl *"; 04034 Constructor += ", void *" + ArgName; 04035 } else { 04036 QualType QT = (*I)->getType(); 04037 if (HasLocalVariableExternalStorage(*I)) 04038 QT = Context->getPointerType(QT); 04039 QT.getAsStringInternal(FieldName, Context->getPrintingPolicy()); 04040 QT.getAsStringInternal(ArgName, Context->getPrintingPolicy()); 04041 Constructor += ", " + ArgName; 04042 } 04043 S += FieldName + ";\n"; 04044 } 04045 // Output all "by ref" declarations. 04046 for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 04047 E = BlockByRefDecls.end(); I != E; ++I) { 04048 S += " "; 04049 std::string FieldName = (*I)->getNameAsString(); 04050 std::string ArgName = "_" + FieldName; 04051 { 04052 std::string TypeString; 04053 RewriteByRefString(TypeString, FieldName, (*I)); 04054 TypeString += " *"; 04055 FieldName = TypeString + FieldName; 04056 ArgName = TypeString + ArgName; 04057 Constructor += ", " + ArgName; 04058 } 04059 S += FieldName + "; // by ref\n"; 04060 } 04061 // Finish writing the constructor. 04062 Constructor += ", int flags=0)"; 04063 // Initialize all "by copy" arguments. 04064 bool firsTime = true; 04065 for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 04066 E = BlockByCopyDecls.end(); I != E; ++I) { 04067 std::string Name = (*I)->getNameAsString(); 04068 if (firsTime) { 04069 Constructor += " : "; 04070 firsTime = false; 04071 } 04072 else 04073 Constructor += ", "; 04074 if (isTopLevelBlockPointerType((*I)->getType())) 04075 Constructor += Name + "((struct __block_impl *)_" + Name + ")"; 04076 else 04077 Constructor += Name + "(_" + Name + ")"; 04078 } 04079 // Initialize all "by ref" arguments. 04080 for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 04081 E = BlockByRefDecls.end(); I != E; ++I) { 04082 std::string Name = (*I)->getNameAsString(); 04083 if (firsTime) { 04084 Constructor += " : "; 04085 firsTime = false; 04086 } 04087 else 04088 Constructor += ", "; 04089 Constructor += Name + "(_" + Name + "->__forwarding)"; 04090 } 04091 04092 Constructor += " {\n"; 04093 if (GlobalVarDecl) 04094 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 04095 else 04096 Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 04097 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 04098 04099 Constructor += " Desc = desc;\n"; 04100 } else { 04101 // Finish writing the constructor. 04102 Constructor += ", int flags=0) {\n"; 04103 if (GlobalVarDecl) 04104 Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; 04105 else 04106 Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; 04107 Constructor += " impl.Flags = flags;\n impl.FuncPtr = fp;\n"; 04108 Constructor += " Desc = desc;\n"; 04109 } 04110 Constructor += " "; 04111 Constructor += "}\n"; 04112 S += Constructor; 04113 S += "};\n"; 04114 return S; 04115 } 04116 04117 std::string RewriteModernObjC::SynthesizeBlockDescriptor(std::string DescTag, 04118 std::string ImplTag, int i, 04119 StringRef FunName, 04120 unsigned hasCopy) { 04121 std::string S = "\nstatic struct " + DescTag; 04122 04123 S += " {\n size_t reserved;\n"; 04124 S += " size_t Block_size;\n"; 04125 if (hasCopy) { 04126 S += " void (*copy)(struct "; 04127 S += ImplTag; S += "*, struct "; 04128 S += ImplTag; S += "*);\n"; 04129 04130 S += " void (*dispose)(struct "; 04131 S += ImplTag; S += "*);\n"; 04132 } 04133 S += "} "; 04134 04135 S += DescTag + "_DATA = { 0, sizeof(struct "; 04136 S += ImplTag + ")"; 04137 if (hasCopy) { 04138 S += ", __" + FunName.str() + "_block_copy_" + utostr(i); 04139 S += ", __" + FunName.str() + "_block_dispose_" + utostr(i); 04140 } 04141 S += "};\n"; 04142 return S; 04143 } 04144 04145 /// getFunctionSourceLocation - returns start location of a function 04146 /// definition. Complication arises when function has declared as 04147 /// extern "C" or extern "C" {...} 04148 static SourceLocation getFunctionSourceLocation (RewriteModernObjC &R, 04149 FunctionDecl *FD) { 04150 if (FD->isExternC() && !FD->isMain()) { 04151 const DeclContext *DC = FD->getDeclContext(); 04152 if (const LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(DC)) 04153 // if it is extern "C" {...}, return function decl's own location. 04154 if (!LSD->getRBraceLoc().isValid()) 04155 return LSD->getExternLoc(); 04156 } 04157 if (FD->getStorageClassAsWritten() != SC_None) 04158 R.RewriteBlockLiteralFunctionDecl(FD); 04159 return FD->getTypeSpecStartLoc(); 04160 } 04161 04162 void RewriteModernObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, 04163 StringRef FunName) { 04164 bool RewriteSC = (GlobalVarDecl && 04165 !Blocks.empty() && 04166 GlobalVarDecl->getStorageClass() == SC_Static && 04167 GlobalVarDecl->getType().getCVRQualifiers()); 04168 if (RewriteSC) { 04169 std::string SC(" void __"); 04170 SC += GlobalVarDecl->getNameAsString(); 04171 SC += "() {}"; 04172 InsertText(FunLocStart, SC); 04173 } 04174 04175 // Insert closures that were part of the function. 04176 for (unsigned i = 0, count=0; i < Blocks.size(); i++) { 04177 CollectBlockDeclRefInfo(Blocks[i]); 04178 // Need to copy-in the inner copied-in variables not actually used in this 04179 // block. 04180 for (int j = 0; j < InnerDeclRefsCount[i]; j++) { 04181 DeclRefExpr *Exp = InnerDeclRefs[count++]; 04182 ValueDecl *VD = Exp->getDecl(); 04183 BlockDeclRefs.push_back(Exp); 04184 if (!VD->hasAttr<BlocksAttr>()) { 04185 if (!BlockByCopyDeclsPtrSet.count(VD)) { 04186 BlockByCopyDeclsPtrSet.insert(VD); 04187 BlockByCopyDecls.push_back(VD); 04188 } 04189 continue; 04190 } 04191 04192 if (!BlockByRefDeclsPtrSet.count(VD)) { 04193 BlockByRefDeclsPtrSet.insert(VD); 04194 BlockByRefDecls.push_back(VD); 04195 } 04196 04197 // imported objects in the inner blocks not used in the outer 04198 // blocks must be copied/disposed in the outer block as well. 04199 if (VD->getType()->isObjCObjectPointerType() || 04200 VD->getType()->isBlockPointerType()) 04201 ImportedBlockDecls.insert(VD); 04202 } 04203 04204 std::string ImplTag = "__" + FunName.str() + "_block_impl_" + utostr(i); 04205 std::string DescTag = "__" + FunName.str() + "_block_desc_" + utostr(i); 04206 04207 std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); 04208 04209 InsertText(FunLocStart, CI); 04210 04211 std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); 04212 04213 InsertText(FunLocStart, CF); 04214 04215 if (ImportedBlockDecls.size()) { 04216 std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); 04217 InsertText(FunLocStart, HF); 04218 } 04219 std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, 04220 ImportedBlockDecls.size() > 0); 04221 InsertText(FunLocStart, BD); 04222 04223 BlockDeclRefs.clear(); 04224 BlockByRefDecls.clear(); 04225 BlockByRefDeclsPtrSet.clear(); 04226 BlockByCopyDecls.clear(); 04227 BlockByCopyDeclsPtrSet.clear(); 04228 ImportedBlockDecls.clear(); 04229 } 04230 if (RewriteSC) { 04231 // Must insert any 'const/volatile/static here. Since it has been 04232 // removed as result of rewriting of block literals. 04233 std::string SC; 04234 if (GlobalVarDecl->getStorageClass() == SC_Static) 04235 SC = "static "; 04236 if (GlobalVarDecl->getType().isConstQualified()) 04237 SC += "const "; 04238 if (GlobalVarDecl->getType().isVolatileQualified()) 04239 SC += "volatile "; 04240 if (GlobalVarDecl->getType().isRestrictQualified()) 04241 SC += "restrict "; 04242 InsertText(FunLocStart, SC); 04243 } 04244 if (GlobalConstructionExp) { 04245 // extra fancy dance for global literal expression. 04246 04247 // Always the latest block expression on the block stack. 04248 std::string Tag = "__"; 04249 Tag += FunName; 04250 Tag += "_block_impl_"; 04251 Tag += utostr(Blocks.size()-1); 04252 std::string globalBuf = "static "; 04253 globalBuf += Tag; globalBuf += " "; 04254 std::string SStr; 04255 04256 llvm::raw_string_ostream constructorExprBuf(SStr); 04257 GlobalConstructionExp->printPretty(constructorExprBuf, *Context, 0, 04258 PrintingPolicy(LangOpts)); 04259 globalBuf += constructorExprBuf.str(); 04260 globalBuf += ";\n"; 04261 InsertText(FunLocStart, globalBuf); 04262 GlobalConstructionExp = 0; 04263 } 04264 04265 Blocks.clear(); 04266 InnerDeclRefsCount.clear(); 04267 InnerDeclRefs.clear(); 04268 RewrittenBlockExprs.clear(); 04269 } 04270 04271 void RewriteModernObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { 04272 SourceLocation FunLocStart = 04273 (!Blocks.empty()) ? getFunctionSourceLocation(*this, FD) 04274 : FD->getTypeSpecStartLoc(); 04275 StringRef FuncName = FD->getName(); 04276 04277 SynthesizeBlockLiterals(FunLocStart, FuncName); 04278 } 04279 04280 static void BuildUniqueMethodName(std::string &Name, 04281 ObjCMethodDecl *MD) { 04282 ObjCInterfaceDecl *IFace = MD->getClassInterface(); 04283 Name = IFace->getName(); 04284 Name += "__" + MD->getSelector().getAsString(); 04285 // Convert colons to underscores. 04286 std::string::size_type loc = 0; 04287 while ((loc = Name.find(":", loc)) != std::string::npos) 04288 Name.replace(loc, 1, "_"); 04289 } 04290 04291 void RewriteModernObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { 04292 //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); 04293 //SourceLocation FunLocStart = MD->getLocStart(); 04294 SourceLocation FunLocStart = MD->getLocStart(); 04295 std::string FuncName; 04296 BuildUniqueMethodName(FuncName, MD); 04297 SynthesizeBlockLiterals(FunLocStart, FuncName); 04298 } 04299 04300 void RewriteModernObjC::GetBlockDeclRefExprs(Stmt *S) { 04301 for (Stmt::child_range CI = S->children(); CI; ++CI) 04302 if (*CI) { 04303 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) 04304 GetBlockDeclRefExprs(CBE->getBody()); 04305 else 04306 GetBlockDeclRefExprs(*CI); 04307 } 04308 // Handle specific things. 04309 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 04310 if (DRE->refersToEnclosingLocal()) { 04311 // FIXME: Handle enums. 04312 if (!isa<FunctionDecl>(DRE->getDecl())) 04313 BlockDeclRefs.push_back(DRE); 04314 if (HasLocalVariableExternalStorage(DRE->getDecl())) 04315 BlockDeclRefs.push_back(DRE); 04316 } 04317 } 04318 04319 return; 04320 } 04321 04322 void RewriteModernObjC::GetInnerBlockDeclRefExprs(Stmt *S, 04323 SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs, 04324 llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) { 04325 for (Stmt::child_range CI = S->children(); CI; ++CI) 04326 if (*CI) { 04327 if (BlockExpr *CBE = dyn_cast<BlockExpr>(*CI)) { 04328 InnerContexts.insert(cast<DeclContext>(CBE->getBlockDecl())); 04329 GetInnerBlockDeclRefExprs(CBE->getBody(), 04330 InnerBlockDeclRefs, 04331 InnerContexts); 04332 } 04333 else 04334 GetInnerBlockDeclRefExprs(*CI, 04335 InnerBlockDeclRefs, 04336 InnerContexts); 04337 04338 } 04339 // Handle specific things. 04340 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 04341 if (DRE->refersToEnclosingLocal()) { 04342 if (!isa<FunctionDecl>(DRE->getDecl()) && 04343 !InnerContexts.count(DRE->getDecl()->getDeclContext())) 04344 InnerBlockDeclRefs.push_back(DRE); 04345 if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) 04346 if (Var->isFunctionOrMethodVarDecl()) 04347 ImportedLocalExternalDecls.insert(Var); 04348 } 04349 } 04350 04351 return; 04352 } 04353 04354 /// convertObjCTypeToCStyleType - This routine converts such objc types 04355 /// as qualified objects, and blocks to their closest c/c++ types that 04356 /// it can. It returns true if input type was modified. 04357 bool RewriteModernObjC::convertObjCTypeToCStyleType(QualType &T) { 04358 QualType oldT = T; 04359 convertBlockPointerToFunctionPointer(T); 04360 if (T->isFunctionPointerType()) { 04361 QualType PointeeTy; 04362 if (const PointerType* PT = T->getAs<PointerType>()) { 04363 PointeeTy = PT->getPointeeType(); 04364 if (const FunctionType *FT = PointeeTy->getAs<FunctionType>()) { 04365 T = convertFunctionTypeOfBlocks(FT); 04366 T = Context->getPointerType(T); 04367 } 04368 } 04369 } 04370 04371 convertToUnqualifiedObjCType(T); 04372 return T != oldT; 04373 } 04374 04375 /// convertFunctionTypeOfBlocks - This routine converts a function type 04376 /// whose result type may be a block pointer or whose argument type(s) 04377 /// might be block pointers to an equivalent function type replacing 04378 /// all block pointers to function pointers. 04379 QualType RewriteModernObjC::convertFunctionTypeOfBlocks(const FunctionType *FT) { 04380 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 04381 // FTP will be null for closures that don't take arguments. 04382 // Generate a funky cast. 04383 SmallVector<QualType, 8> ArgTypes; 04384 QualType Res = FT->getResultType(); 04385 bool modified = convertObjCTypeToCStyleType(Res); 04386 04387 if (FTP) { 04388 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 04389 E = FTP->arg_type_end(); I && (I != E); ++I) { 04390 QualType t = *I; 04391 // Make sure we convert "t (^)(...)" to "t (*)(...)". 04392 if (convertObjCTypeToCStyleType(t)) 04393 modified = true; 04394 ArgTypes.push_back(t); 04395 } 04396 } 04397 QualType FuncType; 04398 if (modified) 04399 FuncType = getSimpleFunctionType(Res, &ArgTypes[0], ArgTypes.size()); 04400 else FuncType = QualType(FT, 0); 04401 return FuncType; 04402 } 04403 04404 Stmt *RewriteModernObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { 04405 // Navigate to relevant type information. 04406 const BlockPointerType *CPT = 0; 04407 04408 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { 04409 CPT = DRE->getType()->getAs<BlockPointerType>(); 04410 } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { 04411 CPT = MExpr->getType()->getAs<BlockPointerType>(); 04412 } 04413 else if (const ParenExpr *PRE = dyn_cast<ParenExpr>(BlockExp)) { 04414 return SynthesizeBlockCall(Exp, PRE->getSubExpr()); 04415 } 04416 else if (const ImplicitCastExpr *IEXPR = dyn_cast<ImplicitCastExpr>(BlockExp)) 04417 CPT = IEXPR->getType()->getAs<BlockPointerType>(); 04418 else if (const ConditionalOperator *CEXPR = 04419 dyn_cast<ConditionalOperator>(BlockExp)) { 04420 Expr *LHSExp = CEXPR->getLHS(); 04421 Stmt *LHSStmt = SynthesizeBlockCall(Exp, LHSExp); 04422 Expr *RHSExp = CEXPR->getRHS(); 04423 Stmt *RHSStmt = SynthesizeBlockCall(Exp, RHSExp); 04424 Expr *CONDExp = CEXPR->getCond(); 04425 ConditionalOperator *CondExpr = 04426 new (Context) ConditionalOperator(CONDExp, 04427 SourceLocation(), cast<Expr>(LHSStmt), 04428 SourceLocation(), cast<Expr>(RHSStmt), 04429 Exp->getType(), VK_RValue, OK_Ordinary); 04430 return CondExpr; 04431 } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { 04432 CPT = IRE->getType()->getAs<BlockPointerType>(); 04433 } else if (const PseudoObjectExpr *POE 04434 = dyn_cast<PseudoObjectExpr>(BlockExp)) { 04435 CPT = POE->getType()->castAs<BlockPointerType>(); 04436 } else { 04437 assert(1 && "RewriteBlockClass: Bad type"); 04438 } 04439 assert(CPT && "RewriteBlockClass: Bad type"); 04440 const FunctionType *FT = CPT->getPointeeType()->getAs<FunctionType>(); 04441 assert(FT && "RewriteBlockClass: Bad type"); 04442 const FunctionProtoType *FTP = dyn_cast<FunctionProtoType>(FT); 04443 // FTP will be null for closures that don't take arguments. 04444 04445 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 04446 SourceLocation(), SourceLocation(), 04447 &Context->Idents.get("__block_impl")); 04448 QualType PtrBlock = Context->getPointerType(Context->getTagDeclType(RD)); 04449 04450 // Generate a funky cast. 04451 SmallVector<QualType, 8> ArgTypes; 04452 04453 // Push the block argument type. 04454 ArgTypes.push_back(PtrBlock); 04455 if (FTP) { 04456 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 04457 E = FTP->arg_type_end(); I && (I != E); ++I) { 04458 QualType t = *I; 04459 // Make sure we convert "t (^)(...)" to "t (*)(...)". 04460 if (!convertBlockPointerToFunctionPointer(t)) 04461 convertToUnqualifiedObjCType(t); 04462 ArgTypes.push_back(t); 04463 } 04464 } 04465 // Now do the pointer to function cast. 04466 QualType PtrToFuncCastType 04467 = getSimpleFunctionType(Exp->getType(), &ArgTypes[0], ArgTypes.size()); 04468 04469 PtrToFuncCastType = Context->getPointerType(PtrToFuncCastType); 04470 04471 CastExpr *BlkCast = NoTypeInfoCStyleCastExpr(Context, PtrBlock, 04472 CK_BitCast, 04473 const_cast<Expr*>(BlockExp)); 04474 // Don't forget the parens to enforce the proper binding. 04475 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 04476 BlkCast); 04477 //PE->dump(); 04478 04479 FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 04480 SourceLocation(), 04481 &Context->Idents.get("FuncPtr"), 04482 Context->VoidPtrTy, 0, 04483 /*BitWidth=*/0, /*Mutable=*/true, 04484 /*HasInit=*/false); 04485 MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 04486 FD->getType(), VK_LValue, 04487 OK_Ordinary); 04488 04489 04490 CastExpr *FunkCast = NoTypeInfoCStyleCastExpr(Context, PtrToFuncCastType, 04491 CK_BitCast, ME); 04492 PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), FunkCast); 04493 04494 SmallVector<Expr*, 8> BlkExprs; 04495 // Add the implicit argument. 04496 BlkExprs.push_back(BlkCast); 04497 // Add the user arguments. 04498 for (CallExpr::arg_iterator I = Exp->arg_begin(), 04499 E = Exp->arg_end(); I != E; ++I) { 04500 BlkExprs.push_back(*I); 04501 } 04502 CallExpr *CE = new (Context) CallExpr(*Context, PE, &BlkExprs[0], 04503 BlkExprs.size(), 04504 Exp->getType(), VK_RValue, 04505 SourceLocation()); 04506 return CE; 04507 } 04508 04509 // We need to return the rewritten expression to handle cases where the 04510 // DeclRefExpr is embedded in another expression being rewritten. 04511 // For example: 04512 // 04513 // int main() { 04514 // __block Foo *f; 04515 // __block int i; 04516 // 04517 // void (^myblock)() = ^() { 04518 // [f test]; // f is a DeclRefExpr embedded in a message (which is being rewritten). 04519 // i = 77; 04520 // }; 04521 //} 04522 Stmt *RewriteModernObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { 04523 // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR 04524 // for each DeclRefExp where BYREFVAR is name of the variable. 04525 ValueDecl *VD = DeclRefExp->getDecl(); 04526 bool isArrow = DeclRefExp->refersToEnclosingLocal(); 04527 04528 FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 04529 SourceLocation(), 04530 &Context->Idents.get("__forwarding"), 04531 Context->VoidPtrTy, 0, 04532 /*BitWidth=*/0, /*Mutable=*/true, 04533 /*HasInit=*/false); 04534 MemberExpr *ME = new (Context) MemberExpr(DeclRefExp, isArrow, 04535 FD, SourceLocation(), 04536 FD->getType(), VK_LValue, 04537 OK_Ordinary); 04538 04539 StringRef Name = VD->getName(); 04540 FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 04541 &Context->Idents.get(Name), 04542 Context->VoidPtrTy, 0, 04543 /*BitWidth=*/0, /*Mutable=*/true, 04544 /*HasInit=*/false); 04545 ME = new (Context) MemberExpr(ME, true, FD, SourceLocation(), 04546 DeclRefExp->getType(), VK_LValue, OK_Ordinary); 04547 04548 04549 04550 // Need parens to enforce precedence. 04551 ParenExpr *PE = new (Context) ParenExpr(DeclRefExp->getExprLoc(), 04552 DeclRefExp->getExprLoc(), 04553 ME); 04554 ReplaceStmt(DeclRefExp, PE); 04555 return PE; 04556 } 04557 04558 // Rewrites the imported local variable V with external storage 04559 // (static, extern, etc.) as *V 04560 // 04561 Stmt *RewriteModernObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) { 04562 ValueDecl *VD = DRE->getDecl(); 04563 if (VarDecl *Var = dyn_cast<VarDecl>(VD)) 04564 if (!ImportedLocalExternalDecls.count(Var)) 04565 return DRE; 04566 Expr *Exp = new (Context) UnaryOperator(DRE, UO_Deref, DRE->getType(), 04567 VK_LValue, OK_Ordinary, 04568 DRE->getLocation()); 04569 // Need parens to enforce precedence. 04570 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 04571 Exp); 04572 ReplaceStmt(DRE, PE); 04573 return PE; 04574 } 04575 04576 void RewriteModernObjC::RewriteCastExpr(CStyleCastExpr *CE) { 04577 SourceLocation LocStart = CE->getLParenLoc(); 04578 SourceLocation LocEnd = CE->getRParenLoc(); 04579 04580 // Need to avoid trying to rewrite synthesized casts. 04581 if (LocStart.isInvalid()) 04582 return; 04583 // Need to avoid trying to rewrite casts contained in macros. 04584 if (!Rewriter::isRewritable(LocStart) || !Rewriter::isRewritable(LocEnd)) 04585 return; 04586 04587 const char *startBuf = SM->getCharacterData(LocStart); 04588 const char *endBuf = SM->getCharacterData(LocEnd); 04589 QualType QT = CE->getType(); 04590 const Type* TypePtr = QT->getAs<Type>(); 04591 if (isa<TypeOfExprType>(TypePtr)) { 04592 const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); 04593 QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); 04594 std::string TypeAsString = "("; 04595 RewriteBlockPointerType(TypeAsString, QT); 04596 TypeAsString += ")"; 04597 ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); 04598 return; 04599 } 04600 // advance the location to startArgList. 04601 const char *argPtr = startBuf; 04602 04603 while (*argPtr++ && (argPtr < endBuf)) { 04604 switch (*argPtr) { 04605 case '^': 04606 // Replace the '^' with '*'. 04607 LocStart = LocStart.getLocWithOffset(argPtr-startBuf); 04608 ReplaceText(LocStart, 1, "*"); 04609 break; 04610 } 04611 } 04612 return; 04613 } 04614 04615 void RewriteModernObjC::RewriteImplicitCastObjCExpr(CastExpr *IC) { 04616 CastKind CastKind = IC->getCastKind(); 04617 if (CastKind != CK_BlockPointerToObjCPointerCast && 04618 CastKind != CK_AnyPointerToBlockPointerCast) 04619 return; 04620 04621 QualType QT = IC->getType(); 04622 (void)convertBlockPointerToFunctionPointer(QT); 04623 std::string TypeString(QT.getAsString(Context->getPrintingPolicy())); 04624 std::string Str = "("; 04625 Str += TypeString; 04626 Str += ")"; 04627 InsertText(IC->getSubExpr()->getLocStart(), &Str[0], Str.size()); 04628 04629 return; 04630 } 04631 04632 void RewriteModernObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { 04633 SourceLocation DeclLoc = FD->getLocation(); 04634 unsigned parenCount = 0; 04635 04636 // We have 1 or more arguments that have closure pointers. 04637 const char *startBuf = SM->getCharacterData(DeclLoc); 04638 const char *startArgList = strchr(startBuf, '('); 04639 04640 assert((*startArgList == '(') && "Rewriter fuzzy parser confused"); 04641 04642 parenCount++; 04643 // advance the location to startArgList. 04644 DeclLoc = DeclLoc.getLocWithOffset(startArgList-startBuf); 04645 assert((DeclLoc.isValid()) && "Invalid DeclLoc"); 04646 04647 const char *argPtr = startArgList; 04648 04649 while (*argPtr++ && parenCount) { 04650 switch (*argPtr) { 04651 case '^': 04652 // Replace the '^' with '*'. 04653 DeclLoc = DeclLoc.getLocWithOffset(argPtr-startArgList); 04654 ReplaceText(DeclLoc, 1, "*"); 04655 break; 04656 case '(': 04657 parenCount++; 04658 break; 04659 case ')': 04660 parenCount--; 04661 break; 04662 } 04663 } 04664 return; 04665 } 04666 04667 bool RewriteModernObjC::PointerTypeTakesAnyBlockArguments(QualType QT) { 04668 const FunctionProtoType *FTP; 04669 const PointerType *PT = QT->getAs<PointerType>(); 04670 if (PT) { 04671 FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 04672 } else { 04673 const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 04674 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 04675 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 04676 } 04677 if (FTP) { 04678 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 04679 E = FTP->arg_type_end(); I != E; ++I) 04680 if (isTopLevelBlockPointerType(*I)) 04681 return true; 04682 } 04683 return false; 04684 } 04685 04686 bool RewriteModernObjC::PointerTypeTakesAnyObjCQualifiedType(QualType QT) { 04687 const FunctionProtoType *FTP; 04688 const PointerType *PT = QT->getAs<PointerType>(); 04689 if (PT) { 04690 FTP = PT->getPointeeType()->getAs<FunctionProtoType>(); 04691 } else { 04692 const BlockPointerType *BPT = QT->getAs<BlockPointerType>(); 04693 assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type"); 04694 FTP = BPT->getPointeeType()->getAs<FunctionProtoType>(); 04695 } 04696 if (FTP) { 04697 for (FunctionProtoType::arg_type_iterator I = FTP->arg_type_begin(), 04698 E = FTP->arg_type_end(); I != E; ++I) { 04699 if ((*I)->isObjCQualifiedIdType()) 04700 return true; 04701 if ((*I)->isObjCObjectPointerType() && 04702 (*I)->getPointeeType()->isObjCQualifiedInterfaceType()) 04703 return true; 04704 } 04705 04706 } 04707 return false; 04708 } 04709 04710 void RewriteModernObjC::GetExtentOfArgList(const char *Name, const char *&LParen, 04711 const char *&RParen) { 04712 const char *argPtr = strchr(Name, '('); 04713 assert((*argPtr == '(') && "Rewriter fuzzy parser confused"); 04714 04715 LParen = argPtr; // output the start. 04716 argPtr++; // skip past the left paren. 04717 unsigned parenCount = 1; 04718 04719 while (*argPtr && parenCount) { 04720 switch (*argPtr) { 04721 case '(': parenCount++; break; 04722 case ')': parenCount--; break; 04723 default: break; 04724 } 04725 if (parenCount) argPtr++; 04726 } 04727 assert((*argPtr == ')') && "Rewriter fuzzy parser confused"); 04728 RParen = argPtr; // output the end 04729 } 04730 04731 void RewriteModernObjC::RewriteBlockPointerDecl(NamedDecl *ND) { 04732 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { 04733 RewriteBlockPointerFunctionArgs(FD); 04734 return; 04735 } 04736 // Handle Variables and Typedefs. 04737 SourceLocation DeclLoc = ND->getLocation(); 04738 QualType DeclT; 04739 if (VarDecl *VD = dyn_cast<VarDecl>(ND)) 04740 DeclT = VD->getType(); 04741 else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND)) 04742 DeclT = TDD->getUnderlyingType(); 04743 else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND)) 04744 DeclT = FD->getType(); 04745 else 04746 llvm_unreachable("RewriteBlockPointerDecl(): Decl type not yet handled"); 04747 04748 const char *startBuf = SM->getCharacterData(DeclLoc); 04749 const char *endBuf = startBuf; 04750 // scan backward (from the decl location) for the end of the previous decl. 04751 while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart) 04752 startBuf--; 04753 SourceLocation Start = DeclLoc.getLocWithOffset(startBuf-endBuf); 04754 std::string buf; 04755 unsigned OrigLength=0; 04756 // *startBuf != '^' if we are dealing with a pointer to function that 04757 // may take block argument types (which will be handled below). 04758 if (*startBuf == '^') { 04759 // Replace the '^' with '*', computing a negative offset. 04760 buf = '*'; 04761 startBuf++; 04762 OrigLength++; 04763 } 04764 while (*startBuf != ')') { 04765 buf += *startBuf; 04766 startBuf++; 04767 OrigLength++; 04768 } 04769 buf += ')'; 04770 OrigLength++; 04771 04772 if (PointerTypeTakesAnyBlockArguments(DeclT) || 04773 PointerTypeTakesAnyObjCQualifiedType(DeclT)) { 04774 // Replace the '^' with '*' for arguments. 04775 // Replace id<P> with id/*<>*/ 04776 DeclLoc = ND->getLocation(); 04777 startBuf = SM->getCharacterData(DeclLoc); 04778 const char *argListBegin, *argListEnd; 04779 GetExtentOfArgList(startBuf, argListBegin, argListEnd); 04780 while (argListBegin < argListEnd) { 04781 if (*argListBegin == '^') 04782 buf += '*'; 04783 else if (*argListBegin == '<') { 04784 buf += "/*"; 04785 buf += *argListBegin++; 04786 OrigLength++;; 04787 while (*argListBegin != '>') { 04788 buf += *argListBegin++; 04789 OrigLength++; 04790 } 04791 buf += *argListBegin; 04792 buf += "*/"; 04793 } 04794 else 04795 buf += *argListBegin; 04796 argListBegin++; 04797 OrigLength++; 04798 } 04799 buf += ')'; 04800 OrigLength++; 04801 } 04802 ReplaceText(Start, OrigLength, buf); 04803 04804 return; 04805 } 04806 04807 04808 /// SynthesizeByrefCopyDestroyHelper - This routine synthesizes: 04809 /// void __Block_byref_id_object_copy(struct Block_byref_id_object *dst, 04810 /// struct Block_byref_id_object *src) { 04811 /// _Block_object_assign (&_dest->object, _src->object, 04812 /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 04813 /// [|BLOCK_FIELD_IS_WEAK]) // object 04814 /// _Block_object_assign(&_dest->object, _src->object, 04815 /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 04816 /// [|BLOCK_FIELD_IS_WEAK]) // block 04817 /// } 04818 /// And: 04819 /// void __Block_byref_id_object_dispose(struct Block_byref_id_object *_src) { 04820 /// _Block_object_dispose(_src->object, 04821 /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT 04822 /// [|BLOCK_FIELD_IS_WEAK]) // object 04823 /// _Block_object_dispose(_src->object, 04824 /// BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK 04825 /// [|BLOCK_FIELD_IS_WEAK]) // block 04826 /// } 04827 04828 std::string RewriteModernObjC::SynthesizeByrefCopyDestroyHelper(VarDecl *VD, 04829 int flag) { 04830 std::string S; 04831 if (CopyDestroyCache.count(flag)) 04832 return S; 04833 CopyDestroyCache.insert(flag); 04834 S = "static void __Block_byref_id_object_copy_"; 04835 S += utostr(flag); 04836 S += "(void *dst, void *src) {\n"; 04837 04838 // offset into the object pointer is computed as: 04839 // void * + void* + int + int + void* + void * 04840 unsigned IntSize = 04841 static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 04842 unsigned VoidPtrSize = 04843 static_cast<unsigned>(Context->getTypeSize(Context->VoidPtrTy)); 04844 04845 unsigned offset = (VoidPtrSize*4 + IntSize + IntSize)/Context->getCharWidth(); 04846 S += " _Block_object_assign((char*)dst + "; 04847 S += utostr(offset); 04848 S += ", *(void * *) ((char*)src + "; 04849 S += utostr(offset); 04850 S += "), "; 04851 S += utostr(flag); 04852 S += ");\n}\n"; 04853 04854 S += "static void __Block_byref_id_object_dispose_"; 04855 S += utostr(flag); 04856 S += "(void *src) {\n"; 04857 S += " _Block_object_dispose(*(void * *) ((char*)src + "; 04858 S += utostr(offset); 04859 S += "), "; 04860 S += utostr(flag); 04861 S += ");\n}\n"; 04862 return S; 04863 } 04864 04865 /// RewriteByRefVar - For each __block typex ND variable this routine transforms 04866 /// the declaration into: 04867 /// struct __Block_byref_ND { 04868 /// void *__isa; // NULL for everything except __weak pointers 04869 /// struct __Block_byref_ND *__forwarding; 04870 /// int32_t __flags; 04871 /// int32_t __size; 04872 /// void *__Block_byref_id_object_copy; // If variable is __block ObjC object 04873 /// void *__Block_byref_id_object_dispose; // If variable is __block ObjC object 04874 /// typex ND; 04875 /// }; 04876 /// 04877 /// It then replaces declaration of ND variable with: 04878 /// struct __Block_byref_ND ND = {__isa=0B, __forwarding=&ND, __flags=some_flag, 04879 /// __size=sizeof(struct __Block_byref_ND), 04880 /// ND=initializer-if-any}; 04881 /// 04882 /// 04883 void RewriteModernObjC::RewriteByRefVar(VarDecl *ND, bool firstDecl, 04884 bool lastDecl) { 04885 int flag = 0; 04886 int isa = 0; 04887 SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); 04888 if (DeclLoc.isInvalid()) 04889 // If type location is missing, it is because of missing type (a warning). 04890 // Use variable's location which is good for this case. 04891 DeclLoc = ND->getLocation(); 04892 const char *startBuf = SM->getCharacterData(DeclLoc); 04893 SourceLocation X = ND->getLocEnd(); 04894 X = SM->getExpansionLoc(X); 04895 const char *endBuf = SM->getCharacterData(X); 04896 std::string Name(ND->getNameAsString()); 04897 std::string ByrefType; 04898 RewriteByRefString(ByrefType, Name, ND, true); 04899 ByrefType += " {\n"; 04900 ByrefType += " void *__isa;\n"; 04901 RewriteByRefString(ByrefType, Name, ND); 04902 ByrefType += " *__forwarding;\n"; 04903 ByrefType += " int __flags;\n"; 04904 ByrefType += " int __size;\n"; 04905 // Add void *__Block_byref_id_object_copy; 04906 // void *__Block_byref_id_object_dispose; if needed. 04907 QualType Ty = ND->getType(); 04908 bool HasCopyAndDispose = Context->BlockRequiresCopying(Ty); 04909 if (HasCopyAndDispose) { 04910 ByrefType += " void (*__Block_byref_id_object_copy)(void*, void*);\n"; 04911 ByrefType += " void (*__Block_byref_id_object_dispose)(void*);\n"; 04912 } 04913 04914 QualType T = Ty; 04915 (void)convertBlockPointerToFunctionPointer(T); 04916 T.getAsStringInternal(Name, Context->getPrintingPolicy()); 04917 04918 ByrefType += " " + Name + ";\n"; 04919 ByrefType += "};\n"; 04920 // Insert this type in global scope. It is needed by helper function. 04921 SourceLocation FunLocStart; 04922 if (CurFunctionDef) 04923 FunLocStart = getFunctionSourceLocation(*this, CurFunctionDef); 04924 else { 04925 assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); 04926 FunLocStart = CurMethodDef->getLocStart(); 04927 } 04928 InsertText(FunLocStart, ByrefType); 04929 04930 if (Ty.isObjCGCWeak()) { 04931 flag |= BLOCK_FIELD_IS_WEAK; 04932 isa = 1; 04933 } 04934 if (HasCopyAndDispose) { 04935 flag = BLOCK_BYREF_CALLER; 04936 QualType Ty = ND->getType(); 04937 // FIXME. Handle __weak variable (BLOCK_FIELD_IS_WEAK) as well. 04938 if (Ty->isBlockPointerType()) 04939 flag |= BLOCK_FIELD_IS_BLOCK; 04940 else 04941 flag |= BLOCK_FIELD_IS_OBJECT; 04942 std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); 04943 if (!HF.empty()) 04944 InsertText(FunLocStart, HF); 04945 } 04946 04947 // struct __Block_byref_ND ND = 04948 // {0, &ND, some_flag, __size=sizeof(struct __Block_byref_ND), 04949 // initializer-if-any}; 04950 bool hasInit = (ND->getInit() != 0); 04951 // FIXME. rewriter does not support __block c++ objects which 04952 // require construction. 04953 if (hasInit) 04954 if (CXXConstructExpr *CExp = dyn_cast<CXXConstructExpr>(ND->getInit())) { 04955 CXXConstructorDecl *CXXDecl = CExp->getConstructor(); 04956 if (CXXDecl && CXXDecl->isDefaultConstructor()) 04957 hasInit = false; 04958 } 04959 04960 unsigned flags = 0; 04961 if (HasCopyAndDispose) 04962 flags |= BLOCK_HAS_COPY_DISPOSE; 04963 Name = ND->getNameAsString(); 04964 ByrefType.clear(); 04965 RewriteByRefString(ByrefType, Name, ND); 04966 std::string ForwardingCastType("("); 04967 ForwardingCastType += ByrefType + " *)"; 04968 ByrefType += " " + Name + " = {(void*)"; 04969 ByrefType += utostr(isa); 04970 ByrefType += "," + ForwardingCastType + "&" + Name + ", "; 04971 ByrefType += utostr(flags); 04972 ByrefType += ", "; 04973 ByrefType += "sizeof("; 04974 RewriteByRefString(ByrefType, Name, ND); 04975 ByrefType += ")"; 04976 if (HasCopyAndDispose) { 04977 ByrefType += ", __Block_byref_id_object_copy_"; 04978 ByrefType += utostr(flag); 04979 ByrefType += ", __Block_byref_id_object_dispose_"; 04980 ByrefType += utostr(flag); 04981 } 04982 04983 if (!firstDecl) { 04984 // In multiple __block declarations, and for all but 1st declaration, 04985 // find location of the separating comma. This would be start location 04986 // where new text is to be inserted. 04987 DeclLoc = ND->getLocation(); 04988 const char *startDeclBuf = SM->getCharacterData(DeclLoc); 04989 const char *commaBuf = startDeclBuf; 04990 while (*commaBuf != ',') 04991 commaBuf--; 04992 assert((*commaBuf == ',') && "RewriteByRefVar: can't find ','"); 04993 DeclLoc = DeclLoc.getLocWithOffset(commaBuf - startDeclBuf); 04994 startBuf = commaBuf; 04995 } 04996 04997 if (!hasInit) { 04998 ByrefType += "};\n"; 04999 unsigned nameSize = Name.size(); 05000 // for block or function pointer declaration. Name is aleady 05001 // part of the declaration. 05002 if (Ty->isBlockPointerType() || Ty->isFunctionPointerType()) 05003 nameSize = 1; 05004 ReplaceText(DeclLoc, endBuf-startBuf+nameSize, ByrefType); 05005 } 05006 else { 05007 ByrefType += ", "; 05008 SourceLocation startLoc; 05009 Expr *E = ND->getInit(); 05010 if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) 05011 startLoc = ECE->getLParenLoc(); 05012 else 05013 startLoc = E->getLocStart(); 05014 startLoc = SM->getExpansionLoc(startLoc); 05015 endBuf = SM->getCharacterData(startLoc); 05016 ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); 05017 05018 const char separator = lastDecl ? ';' : ','; 05019 const char *startInitializerBuf = SM->getCharacterData(startLoc); 05020 const char *separatorBuf = strchr(startInitializerBuf, separator); 05021 assert((*separatorBuf == separator) && 05022 "RewriteByRefVar: can't find ';' or ','"); 05023 SourceLocation separatorLoc = 05024 startLoc.getLocWithOffset(separatorBuf-startInitializerBuf); 05025 05026 InsertText(separatorLoc, lastDecl ? "}" : "};\n"); 05027 } 05028 return; 05029 } 05030 05031 void RewriteModernObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { 05032 // Add initializers for any closure decl refs. 05033 GetBlockDeclRefExprs(Exp->getBody()); 05034 if (BlockDeclRefs.size()) { 05035 // Unique all "by copy" declarations. 05036 for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 05037 if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 05038 if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 05039 BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 05040 BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); 05041 } 05042 } 05043 // Unique all "by ref" declarations. 05044 for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 05045 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { 05046 if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { 05047 BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); 05048 BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); 05049 } 05050 } 05051 // Find any imported blocks...they will need special attention. 05052 for (unsigned i = 0; i < BlockDeclRefs.size(); i++) 05053 if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 05054 BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 05055 BlockDeclRefs[i]->getType()->isBlockPointerType()) 05056 ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); 05057 } 05058 } 05059 05060 FunctionDecl *RewriteModernObjC::SynthBlockInitFunctionDecl(StringRef name) { 05061 IdentifierInfo *ID = &Context->Idents.get(name); 05062 QualType FType = Context->getFunctionNoProtoType(Context->VoidPtrTy); 05063 return FunctionDecl::Create(*Context, TUDecl, SourceLocation(), 05064 SourceLocation(), ID, FType, 0, SC_Extern, 05065 SC_None, false, false); 05066 } 05067 05068 Stmt *RewriteModernObjC::SynthBlockInitExpr(BlockExpr *Exp, 05069 const SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs) { 05070 05071 const BlockDecl *block = Exp->getBlockDecl(); 05072 05073 Blocks.push_back(Exp); 05074 05075 CollectBlockDeclRefInfo(Exp); 05076 05077 // Add inner imported variables now used in current block. 05078 int countOfInnerDecls = 0; 05079 if (!InnerBlockDeclRefs.empty()) { 05080 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { 05081 DeclRefExpr *Exp = InnerBlockDeclRefs[i]; 05082 ValueDecl *VD = Exp->getDecl(); 05083 if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { 05084 // We need to save the copied-in variables in nested 05085 // blocks because it is needed at the end for some of the API generations. 05086 // See SynthesizeBlockLiterals routine. 05087 InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 05088 BlockDeclRefs.push_back(Exp); 05089 BlockByCopyDeclsPtrSet.insert(VD); 05090 BlockByCopyDecls.push_back(VD); 05091 } 05092 if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { 05093 InnerDeclRefs.push_back(Exp); countOfInnerDecls++; 05094 BlockDeclRefs.push_back(Exp); 05095 BlockByRefDeclsPtrSet.insert(VD); 05096 BlockByRefDecls.push_back(VD); 05097 } 05098 } 05099 // Find any imported blocks...they will need special attention. 05100 for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) 05101 if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || 05102 InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || 05103 InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) 05104 ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); 05105 } 05106 InnerDeclRefsCount.push_back(countOfInnerDecls); 05107 05108 std::string FuncName; 05109 05110 if (CurFunctionDef) 05111 FuncName = CurFunctionDef->getNameAsString(); 05112 else if (CurMethodDef) 05113 BuildUniqueMethodName(FuncName, CurMethodDef); 05114 else if (GlobalVarDecl) 05115 FuncName = std::string(GlobalVarDecl->getNameAsString()); 05116 05117 bool GlobalBlockExpr = 05118 block->getDeclContext()->getRedeclContext()->isFileContext(); 05119 05120 if (GlobalBlockExpr && !GlobalVarDecl) { 05121 Diags.Report(block->getLocation(), GlobalBlockRewriteFailedDiag); 05122 GlobalBlockExpr = false; 05123 } 05124 05125 std::string BlockNumber = utostr(Blocks.size()-1); 05126 05127 std::string Func = "__" + FuncName + "_block_func_" + BlockNumber; 05128 05129 // Get a pointer to the function type so we can cast appropriately. 05130 QualType BFT = convertFunctionTypeOfBlocks(Exp->getFunctionType()); 05131 QualType FType = Context->getPointerType(BFT); 05132 05133 FunctionDecl *FD; 05134 Expr *NewRep; 05135 05136 // Simulate a contructor call... 05137 std::string Tag; 05138 05139 if (GlobalBlockExpr) 05140 Tag = "__global_"; 05141 else 05142 Tag = "__"; 05143 Tag += FuncName + "_block_impl_" + BlockNumber; 05144 05145 FD = SynthBlockInitFunctionDecl(Tag); 05146 DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue, 05147 SourceLocation()); 05148 05149 SmallVector<Expr*, 4> InitExprs; 05150 05151 // Initialize the block function. 05152 FD = SynthBlockInitFunctionDecl(Func); 05153 DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), 05154 VK_LValue, SourceLocation()); 05155 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 05156 CK_BitCast, Arg); 05157 InitExprs.push_back(castExpr); 05158 05159 // Initialize the block descriptor. 05160 std::string DescData = "__" + FuncName + "_block_desc_" + BlockNumber + "_DATA"; 05161 05162 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, 05163 SourceLocation(), SourceLocation(), 05164 &Context->Idents.get(DescData.c_str()), 05165 Context->VoidPtrTy, 0, 05166 SC_Static, SC_None); 05167 UnaryOperator *DescRefExpr = 05168 new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false, 05169 Context->VoidPtrTy, 05170 VK_LValue, 05171 SourceLocation()), 05172 UO_AddrOf, 05173 Context->getPointerType(Context->VoidPtrTy), 05174 VK_RValue, OK_Ordinary, 05175 SourceLocation()); 05176 InitExprs.push_back(DescRefExpr); 05177 05178 // Add initializers for any closure decl refs. 05179 if (BlockDeclRefs.size()) { 05180 Expr *Exp; 05181 // Output all "by copy" declarations. 05182 for (SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), 05183 E = BlockByCopyDecls.end(); I != E; ++I) { 05184 if (isObjCType((*I)->getType())) { 05185 // FIXME: Conform to ABI ([[obj retain] autorelease]). 05186 FD = SynthBlockInitFunctionDecl((*I)->getName()); 05187 Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), 05188 VK_LValue, SourceLocation()); 05189 if (HasLocalVariableExternalStorage(*I)) { 05190 QualType QT = (*I)->getType(); 05191 QT = Context->getPointerType(QT); 05192 Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 05193 OK_Ordinary, SourceLocation()); 05194 } 05195 } else if (isTopLevelBlockPointerType((*I)->getType())) { 05196 FD = SynthBlockInitFunctionDecl((*I)->getName()); 05197 Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), 05198 VK_LValue, SourceLocation()); 05199 Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, 05200 CK_BitCast, Arg); 05201 } else { 05202 FD = SynthBlockInitFunctionDecl((*I)->getName()); 05203 Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), 05204 VK_LValue, SourceLocation()); 05205 if (HasLocalVariableExternalStorage(*I)) { 05206 QualType QT = (*I)->getType(); 05207 QT = Context->getPointerType(QT); 05208 Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, QT, VK_RValue, 05209 OK_Ordinary, SourceLocation()); 05210 } 05211 05212 } 05213 InitExprs.push_back(Exp); 05214 } 05215 // Output all "by ref" declarations. 05216 for (SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), 05217 E = BlockByRefDecls.end(); I != E; ++I) { 05218 ValueDecl *ND = (*I); 05219 std::string Name(ND->getNameAsString()); 05220 std::string RecName; 05221 RewriteByRefString(RecName, Name, ND, true); 05222 IdentifierInfo *II = &Context->Idents.get(RecName.c_str() 05223 + sizeof("struct")); 05224 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 05225 SourceLocation(), SourceLocation(), 05226 II); 05227 assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); 05228 QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); 05229 05230 FD = SynthBlockInitFunctionDecl((*I)->getName()); 05231 Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, 05232 SourceLocation()); 05233 bool isNestedCapturedVar = false; 05234 if (block) 05235 for (BlockDecl::capture_const_iterator ci = block->capture_begin(), 05236 ce = block->capture_end(); ci != ce; ++ci) { 05237 const VarDecl *variable = ci->getVariable(); 05238 if (variable == ND && ci->isNested()) { 05239 assert (ci->isByRef() && 05240 "SynthBlockInitExpr - captured block variable is not byref"); 05241 isNestedCapturedVar = true; 05242 break; 05243 } 05244 } 05245 // captured nested byref variable has its address passed. Do not take 05246 // its address again. 05247 if (!isNestedCapturedVar) 05248 Exp = new (Context) UnaryOperator(Exp, UO_AddrOf, 05249 Context->getPointerType(Exp->getType()), 05250 VK_RValue, OK_Ordinary, SourceLocation()); 05251 Exp = NoTypeInfoCStyleCastExpr(Context, castT, CK_BitCast, Exp); 05252 InitExprs.push_back(Exp); 05253 } 05254 } 05255 if (ImportedBlockDecls.size()) { 05256 // generate BLOCK_HAS_COPY_DISPOSE(have helper funcs) | BLOCK_HAS_DESCRIPTOR 05257 int flag = (BLOCK_HAS_COPY_DISPOSE | BLOCK_HAS_DESCRIPTOR); 05258 unsigned IntSize = 05259 static_cast<unsigned>(Context->getTypeSize(Context->IntTy)); 05260 Expr *FlagExp = IntegerLiteral::Create(*Context, llvm::APInt(IntSize, flag), 05261 Context->IntTy, SourceLocation()); 05262 InitExprs.push_back(FlagExp); 05263 } 05264 NewRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(), 05265 FType, VK_LValue, SourceLocation()); 05266 05267 if (GlobalBlockExpr) { 05268 assert (GlobalConstructionExp == 0 && 05269 "SynthBlockInitExpr - GlobalConstructionExp must be null"); 05270 GlobalConstructionExp = NewRep; 05271 NewRep = DRE; 05272 } 05273 05274 NewRep = new (Context) UnaryOperator(NewRep, UO_AddrOf, 05275 Context->getPointerType(NewRep->getType()), 05276 VK_RValue, OK_Ordinary, SourceLocation()); 05277 NewRep = NoTypeInfoCStyleCastExpr(Context, FType, CK_BitCast, 05278 NewRep); 05279 BlockDeclRefs.clear(); 05280 BlockByRefDecls.clear(); 05281 BlockByRefDeclsPtrSet.clear(); 05282 BlockByCopyDecls.clear(); 05283 BlockByCopyDeclsPtrSet.clear(); 05284 ImportedBlockDecls.clear(); 05285 return NewRep; 05286 } 05287 05288 bool RewriteModernObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { 05289 if (const ObjCForCollectionStmt * CS = 05290 dyn_cast<ObjCForCollectionStmt>(Stmts.back())) 05291 return CS->getElement() == DS; 05292 return false; 05293 } 05294 05295 //===----------------------------------------------------------------------===// 05296 // Function Body / Expression rewriting 05297 //===----------------------------------------------------------------------===// 05298 05299 Stmt *RewriteModernObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { 05300 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 05301 isa<DoStmt>(S) || isa<ForStmt>(S)) 05302 Stmts.push_back(S); 05303 else if (isa<ObjCForCollectionStmt>(S)) { 05304 Stmts.push_back(S); 05305 ObjCBcLabelNo.push_back(++BcLabelCount); 05306 } 05307 05308 // Pseudo-object operations and ivar references need special 05309 // treatment because we're going to recursively rewrite them. 05310 if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) { 05311 if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) { 05312 return RewritePropertyOrImplicitSetter(PseudoOp); 05313 } else { 05314 return RewritePropertyOrImplicitGetter(PseudoOp); 05315 } 05316 } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { 05317 return RewriteObjCIvarRefExpr(IvarRefExpr); 05318 } 05319 05320 SourceRange OrigStmtRange = S->getSourceRange(); 05321 05322 // Perform a bottom up rewrite of all children. 05323 for (Stmt::child_range CI = S->children(); CI; ++CI) 05324 if (*CI) { 05325 Stmt *childStmt = (*CI); 05326 Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt); 05327 if (newStmt) { 05328 *CI = newStmt; 05329 } 05330 } 05331 05332 if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { 05333 SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs; 05334 llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; 05335 InnerContexts.insert(BE->getBlockDecl()); 05336 ImportedLocalExternalDecls.clear(); 05337 GetInnerBlockDeclRefExprs(BE->getBody(), 05338 InnerBlockDeclRefs, InnerContexts); 05339 // Rewrite the block body in place. 05340 Stmt *SaveCurrentBody = CurrentBody; 05341 CurrentBody = BE->getBody(); 05342 PropParentMap = 0; 05343 // block literal on rhs of a property-dot-sytax assignment 05344 // must be replaced by its synthesize ast so getRewrittenText 05345 // works as expected. In this case, what actually ends up on RHS 05346 // is the blockTranscribed which is the helper function for the 05347 // block literal; as in: self.c = ^() {[ace ARR];}; 05348 bool saveDisableReplaceStmt = DisableReplaceStmt; 05349 DisableReplaceStmt = false; 05350 RewriteFunctionBodyOrGlobalInitializer(BE->getBody()); 05351 DisableReplaceStmt = saveDisableReplaceStmt; 05352 CurrentBody = SaveCurrentBody; 05353 PropParentMap = 0; 05354 ImportedLocalExternalDecls.clear(); 05355 // Now we snarf the rewritten text and stash it away for later use. 05356 std::string Str = Rewrite.getRewrittenText(BE->getSourceRange()); 05357 RewrittenBlockExprs[BE] = Str; 05358 05359 Stmt *blockTranscribed = SynthBlockInitExpr(BE, InnerBlockDeclRefs); 05360 05361 //blockTranscribed->dump(); 05362 ReplaceStmt(S, blockTranscribed); 05363 return blockTranscribed; 05364 } 05365 // Handle specific things. 05366 if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) 05367 return RewriteAtEncode(AtEncode); 05368 05369 if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) 05370 return RewriteAtSelector(AtSelector); 05371 05372 if (ObjCStringLiteral *AtString = dyn_cast<ObjCStringLiteral>(S)) 05373 return RewriteObjCStringLiteral(AtString); 05374 05375 if (ObjCBoolLiteralExpr *BoolLitExpr = dyn_cast<ObjCBoolLiteralExpr>(S)) 05376 return RewriteObjCBoolLiteralExpr(BoolLitExpr); 05377 05378 if (ObjCBoxedExpr *BoxedExpr = dyn_cast<ObjCBoxedExpr>(S)) 05379 return RewriteObjCBoxedExpr(BoxedExpr); 05380 05381 if (ObjCArrayLiteral *ArrayLitExpr = dyn_cast<ObjCArrayLiteral>(S)) 05382 return RewriteObjCArrayLiteralExpr(ArrayLitExpr); 05383 05384 if (ObjCDictionaryLiteral *DictionaryLitExpr = 05385 dyn_cast<ObjCDictionaryLiteral>(S)) 05386 return RewriteObjCDictionaryLiteralExpr(DictionaryLitExpr); 05387 05388 if (ObjCMessageExpr *MessExpr = dyn_cast<ObjCMessageExpr>(S)) { 05389 #if 0 05390 // Before we rewrite it, put the original message expression in a comment. 05391 SourceLocation startLoc = MessExpr->getLocStart(); 05392 SourceLocation endLoc = MessExpr->getLocEnd(); 05393 05394 const char *startBuf = SM->getCharacterData(startLoc); 05395 const char *endBuf = SM->getCharacterData(endLoc); 05396 05397 std::string messString; 05398 messString += "// "; 05399 messString.append(startBuf, endBuf-startBuf+1); 05400 messString += "\n"; 05401 05402 // FIXME: Missing definition of 05403 // InsertText(clang::SourceLocation, char const*, unsigned int). 05404 // InsertText(startLoc, messString.c_str(), messString.size()); 05405 // Tried this, but it didn't work either... 05406 // ReplaceText(startLoc, 0, messString.c_str(), messString.size()); 05407 #endif 05408 return RewriteMessageExpr(MessExpr); 05409 } 05410 05411 if (ObjCAtTryStmt *StmtTry = dyn_cast<ObjCAtTryStmt>(S)) 05412 return RewriteObjCTryStmt(StmtTry); 05413 05414 if (ObjCAtSynchronizedStmt *StmtTry = dyn_cast<ObjCAtSynchronizedStmt>(S)) 05415 return RewriteObjCSynchronizedStmt(StmtTry); 05416 05417 if (ObjCAtThrowStmt *StmtThrow = dyn_cast<ObjCAtThrowStmt>(S)) 05418 return RewriteObjCThrowStmt(StmtThrow); 05419 05420 if (ObjCProtocolExpr *ProtocolExp = dyn_cast<ObjCProtocolExpr>(S)) 05421 return RewriteObjCProtocolExpr(ProtocolExp); 05422 05423 if (ObjCForCollectionStmt *StmtForCollection = 05424 dyn_cast<ObjCForCollectionStmt>(S)) 05425 return RewriteObjCForCollectionStmt(StmtForCollection, 05426 OrigStmtRange.getEnd()); 05427 if (BreakStmt *StmtBreakStmt = 05428 dyn_cast<BreakStmt>(S)) 05429 return RewriteBreakStmt(StmtBreakStmt); 05430 if (ContinueStmt *StmtContinueStmt = 05431 dyn_cast<ContinueStmt>(S)) 05432 return RewriteContinueStmt(StmtContinueStmt); 05433 05434 // Need to check for protocol refs (id <P>, Foo <P> *) in variable decls 05435 // and cast exprs. 05436 if (DeclStmt *DS = dyn_cast<DeclStmt>(S)) { 05437 // FIXME: What we're doing here is modifying the type-specifier that 05438 // precedes the first Decl. In the future the DeclGroup should have 05439 // a separate type-specifier that we can rewrite. 05440 // NOTE: We need to avoid rewriting the DeclStmt if it is within 05441 // the context of an ObjCForCollectionStmt. For example: 05442 // NSArray *someArray; 05443 // for (id <FooProtocol> index in someArray) ; 05444 // This is because RewriteObjCForCollectionStmt() does textual rewriting 05445 // and it depends on the original text locations/positions. 05446 if (Stmts.empty() || !IsDeclStmtInForeachHeader(DS)) 05447 RewriteObjCQualifiedInterfaceTypes(*DS->decl_begin()); 05448 05449 // Blocks rewrite rules. 05450 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end(); 05451 DI != DE; ++DI) { 05452 Decl *SD = *DI; 05453 if (ValueDecl *ND = dyn_cast<ValueDecl>(SD)) { 05454 if (isTopLevelBlockPointerType(ND->getType())) 05455 RewriteBlockPointerDecl(ND); 05456 else if (ND->getType()->isFunctionPointerType()) 05457 CheckFunctionPointerDecl(ND->getType(), ND); 05458 if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { 05459 if (VD->hasAttr<BlocksAttr>()) { 05460 static unsigned uniqueByrefDeclCount = 0; 05461 assert(!BlockByRefDeclNo.count(ND) && 05462 "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl"); 05463 BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; 05464 RewriteByRefVar(VD, (DI == DS->decl_begin()), ((DI+1) == DE)); 05465 } 05466 else 05467 RewriteTypeOfDecl(VD); 05468 } 05469 } 05470 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) { 05471 if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 05472 RewriteBlockPointerDecl(TD); 05473 else if (TD->getUnderlyingType()->isFunctionPointerType()) 05474 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 05475 } 05476 } 05477 } 05478 05479 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) 05480 RewriteObjCQualifiedInterfaceTypes(CE); 05481 05482 if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || 05483 isa<DoStmt>(S) || isa<ForStmt>(S)) { 05484 assert(!Stmts.empty() && "Statement stack is empty"); 05485 assert ((isa<SwitchStmt>(Stmts.back()) || isa<WhileStmt>(Stmts.back()) || 05486 isa<DoStmt>(Stmts.back()) || isa<ForStmt>(Stmts.back())) 05487 && "Statement stack mismatch"); 05488 Stmts.pop_back(); 05489 } 05490 // Handle blocks rewriting. 05491 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { 05492 ValueDecl *VD = DRE->getDecl(); 05493 if (VD->hasAttr<BlocksAttr>()) 05494 return RewriteBlockDeclRefExpr(DRE); 05495 if (HasLocalVariableExternalStorage(VD)) 05496 return RewriteLocalVariableExternalStorage(DRE); 05497 } 05498 05499 if (CallExpr *CE = dyn_cast<CallExpr>(S)) { 05500 if (CE->getCallee()->getType()->isBlockPointerType()) { 05501 Stmt *BlockCall = SynthesizeBlockCall(CE, CE->getCallee()); 05502 ReplaceStmt(S, BlockCall); 05503 return BlockCall; 05504 } 05505 } 05506 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(S)) { 05507 RewriteCastExpr(CE); 05508 } 05509 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 05510 RewriteImplicitCastObjCExpr(ICE); 05511 } 05512 #if 0 05513 05514 if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(S)) { 05515 CastExpr *Replacement = new (Context) CastExpr(ICE->getType(), 05516 ICE->getSubExpr(), 05517 SourceLocation()); 05518 // Get the new text. 05519 std::string SStr; 05520 llvm::raw_string_ostream Buf(SStr); 05521 Replacement->printPretty(Buf, *Context); 05522 const std::string &Str = Buf.str(); 05523 05524 printf("CAST = %s\n", &Str[0]); 05525 InsertText(ICE->getSubExpr()->getLocStart(), &Str[0], Str.size()); 05526 delete S; 05527 return Replacement; 05528 } 05529 #endif 05530 // Return this stmt unmodified. 05531 return S; 05532 } 05533 05534 void RewriteModernObjC::RewriteRecordBody(RecordDecl *RD) { 05535 for (RecordDecl::field_iterator i = RD->field_begin(), 05536 e = RD->field_end(); i != e; ++i) { 05537 FieldDecl *FD = &*i; 05538 if (isTopLevelBlockPointerType(FD->getType())) 05539 RewriteBlockPointerDecl(FD); 05540 if (FD->getType()->isObjCQualifiedIdType() || 05541 FD->getType()->isObjCQualifiedInterfaceType()) 05542 RewriteObjCQualifiedInterfaceTypes(FD); 05543 } 05544 } 05545 05546 /// HandleDeclInMainFile - This is called for each top-level decl defined in the 05547 /// main file of the input. 05548 void RewriteModernObjC::HandleDeclInMainFile(Decl *D) { 05549 switch (D->getKind()) { 05550 case Decl::Function: { 05551 FunctionDecl *FD = cast<FunctionDecl>(D); 05552 if (FD->isOverloadedOperator()) 05553 return; 05554 05555 // Since function prototypes don't have ParmDecl's, we check the function 05556 // prototype. This enables us to rewrite function declarations and 05557 // definitions using the same code. 05558 RewriteBlocksInFunctionProtoType(FD->getType(), FD); 05559 05560 if (!FD->isThisDeclarationADefinition()) 05561 break; 05562 05563 // FIXME: If this should support Obj-C++, support CXXTryStmt 05564 if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { 05565 CurFunctionDef = FD; 05566 CurrentBody = Body; 05567 Body = 05568 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 05569 FD->setBody(Body); 05570 CurrentBody = 0; 05571 if (PropParentMap) { 05572 delete PropParentMap; 05573 PropParentMap = 0; 05574 } 05575 // This synthesizes and inserts the block "impl" struct, invoke function, 05576 // and any copy/dispose helper functions. 05577 InsertBlockLiteralsWithinFunction(FD); 05578 CurFunctionDef = 0; 05579 } 05580 break; 05581 } 05582 case Decl::ObjCMethod: { 05583 ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); 05584 if (CompoundStmt *Body = MD->getCompoundBody()) { 05585 CurMethodDef = MD; 05586 CurrentBody = Body; 05587 Body = 05588 cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); 05589 MD->setBody(Body); 05590 CurrentBody = 0; 05591 if (PropParentMap) { 05592 delete PropParentMap; 05593 PropParentMap = 0; 05594 } 05595 InsertBlockLiteralsWithinMethod(MD); 05596 CurMethodDef = 0; 05597 } 05598 break; 05599 } 05600 case Decl::ObjCImplementation: { 05601 ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D); 05602 ClassImplementation.push_back(CI); 05603 break; 05604 } 05605 case Decl::ObjCCategoryImpl: { 05606 ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D); 05607 CategoryImplementation.push_back(CI); 05608 break; 05609 } 05610 case Decl::Var: { 05611 VarDecl *VD = cast<VarDecl>(D); 05612 RewriteObjCQualifiedInterfaceTypes(VD); 05613 if (isTopLevelBlockPointerType(VD->getType())) 05614 RewriteBlockPointerDecl(VD); 05615 else if (VD->getType()->isFunctionPointerType()) { 05616 CheckFunctionPointerDecl(VD->getType(), VD); 05617 if (VD->getInit()) { 05618 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 05619 RewriteCastExpr(CE); 05620 } 05621 } 05622 } else if (VD->getType()->isRecordType()) { 05623 RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl(); 05624 if (RD->isCompleteDefinition()) 05625 RewriteRecordBody(RD); 05626 } 05627 if (VD->getInit()) { 05628 GlobalVarDecl = VD; 05629 CurrentBody = VD->getInit(); 05630 RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); 05631 CurrentBody = 0; 05632 if (PropParentMap) { 05633 delete PropParentMap; 05634 PropParentMap = 0; 05635 } 05636 SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName()); 05637 GlobalVarDecl = 0; 05638 05639 // This is needed for blocks. 05640 if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { 05641 RewriteCastExpr(CE); 05642 } 05643 } 05644 break; 05645 } 05646 case Decl::TypeAlias: 05647 case Decl::Typedef: { 05648 if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { 05649 if (isTopLevelBlockPointerType(TD->getUnderlyingType())) 05650 RewriteBlockPointerDecl(TD); 05651 else if (TD->getUnderlyingType()->isFunctionPointerType()) 05652 CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); 05653 } 05654 break; 05655 } 05656 case Decl::CXXRecord: 05657 case Decl::Record: { 05658 RecordDecl *RD = cast<RecordDecl>(D); 05659 if (RD->isCompleteDefinition()) 05660 RewriteRecordBody(RD); 05661 break; 05662 } 05663 default: 05664 break; 05665 } 05666 // Nothing yet. 05667 } 05668 05669 /// Write_ProtocolExprReferencedMetadata - This routine writer out the 05670 /// protocol reference symbols in the for of: 05671 /// struct _protocol_t *PROTOCOL_REF = &PROTOCOL_METADATA. 05672 static void Write_ProtocolExprReferencedMetadata(ASTContext *Context, 05673 ObjCProtocolDecl *PDecl, 05674 std::string &Result) { 05675 // Also output .objc_protorefs$B section and its meta-data. 05676 if (Context->getLangOpts().MicrosoftExt) 05677 Result += "static "; 05678 Result += "struct _protocol_t *"; 05679 Result += "_OBJC_PROTOCOL_REFERENCE_$_"; 05680 Result += PDecl->getNameAsString(); 05681 Result += " = &"; 05682 Result += "_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString(); 05683 Result += ";\n"; 05684 } 05685 05686 void RewriteModernObjC::HandleTranslationUnit(ASTContext &C) { 05687 if (Diags.hasErrorOccurred()) 05688 return; 05689 05690 RewriteInclude(); 05691 05692 // Here's a great place to add any extra declarations that may be needed. 05693 // Write out meta data for each @protocol(<expr>). 05694 for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), 05695 E = ProtocolExprDecls.end(); I != E; ++I) { 05696 RewriteObjCProtocolMetaData(*I, Preamble); 05697 Write_ProtocolExprReferencedMetadata(Context, (*I), Preamble); 05698 } 05699 05700 InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); 05701 05702 if (ClassImplementation.size() || CategoryImplementation.size()) 05703 RewriteImplementations(); 05704 05705 for (unsigned i = 0, e = ObjCInterfacesSeen.size(); i < e; i++) { 05706 ObjCInterfaceDecl *CDecl = ObjCInterfacesSeen[i]; 05707 // Write struct declaration for the class matching its ivar declarations. 05708 // Note that for modern abi, this is postponed until the end of TU 05709 // because class extensions and the implementation might declare their own 05710 // private ivars. 05711 RewriteInterfaceDecl(CDecl); 05712 } 05713 05714 // Get the buffer corresponding to MainFileID. If we haven't changed it, then 05715 // we are done. 05716 if (const RewriteBuffer *RewriteBuf = 05717 Rewrite.getRewriteBufferFor(MainFileID)) { 05718 //printf("Changed:\n"); 05719 *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); 05720 } else { 05721 llvm::errs() << "No changes\n"; 05722 } 05723 05724 if (ClassImplementation.size() || CategoryImplementation.size() || 05725 ProtocolExprDecls.size()) { 05726 // Rewrite Objective-c meta data* 05727 std::string ResultStr; 05728 RewriteMetaDataIntoBuffer(ResultStr); 05729 // Emit metadata. 05730 *OutFile << ResultStr; 05731 } 05732 // Emit ImageInfo; 05733 { 05734 std::string ResultStr; 05735 WriteImageInfo(ResultStr); 05736 *OutFile << ResultStr; 05737 } 05738 OutFile->flush(); 05739 } 05740 05741 void RewriteModernObjC::Initialize(ASTContext &context) { 05742 InitializeCommon(context); 05743 05744 Preamble += "#ifndef __OBJC2__\n"; 05745 Preamble += "#define __OBJC2__\n"; 05746 Preamble += "#endif\n"; 05747 05748 // declaring objc_selector outside the parameter list removes a silly 05749 // scope related warning... 05750 if (IsHeader) 05751 Preamble = "#pragma once\n"; 05752 Preamble += "struct objc_selector; struct objc_class;\n"; 05753 Preamble += "struct __rw_objc_super { \n\tstruct objc_object *object; "; 05754 Preamble += "\n\tstruct objc_object *superClass; "; 05755 // Add a constructor for creating temporary objects. 05756 Preamble += "\n\t__rw_objc_super(struct objc_object *o, struct objc_object *s) "; 05757 Preamble += ": object(o), superClass(s) {} "; 05758 Preamble += "\n};\n"; 05759 05760 if (LangOpts.MicrosoftExt) { 05761 // Define all sections using syntax that makes sense. 05762 // These are currently generated. 05763 Preamble += "\n#pragma section(\".objc_classlist$B\", long, read, write)\n"; 05764 Preamble += "#pragma section(\".objc_catlist$B\", long, read, write)\n"; 05765 Preamble += "#pragma section(\".objc_imageinfo$B\", long, read, write)\n"; 05766 Preamble += "#pragma section(\".objc_nlclslist$B\", long, read, write)\n"; 05767 Preamble += "#pragma section(\".objc_nlcatlist$B\", long, read, write)\n"; 05768 // These are generated but not necessary for functionality. 05769 Preamble += "#pragma section(\".cat_cls_meth$B\", long, read, write)\n"; 05770 Preamble += "#pragma section(\".inst_meth$B\", long, read, write)\n"; 05771 Preamble += "#pragma section(\".cls_meth$B\", long, read, write)\n"; 05772 Preamble += "#pragma section(\".objc_ivar$B\", long, read, write)\n"; 05773 05774 // These need be generated for performance. Currently they are not, 05775 // using API calls instead. 05776 Preamble += "#pragma section(\".objc_selrefs$B\", long, read, write)\n"; 05777 Preamble += "#pragma section(\".objc_classrefs$B\", long, read, write)\n"; 05778 Preamble += "#pragma section(\".objc_superrefs$B\", long, read, write)\n"; 05779 05780 } 05781 Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; 05782 Preamble += "typedef struct objc_object Protocol;\n"; 05783 Preamble += "#define _REWRITER_typedef_Protocol\n"; 05784 Preamble += "#endif\n"; 05785 if (LangOpts.MicrosoftExt) { 05786 Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; 05787 Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; 05788 } 05789 else 05790 Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; 05791 05792 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend(void);\n"; 05793 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper(void);\n"; 05794 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_stret(void);\n"; 05795 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSendSuper_stret(void);\n"; 05796 Preamble += "__OBJC_RW_DLLIMPORT void objc_msgSend_fpret(void);\n"; 05797 05798 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getClass"; 05799 Preamble += "(const char *);\n"; 05800 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; 05801 Preamble += "(struct objc_class *);\n"; 05802 Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *objc_getMetaClass"; 05803 Preamble += "(const char *);\n"; 05804 Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw( struct objc_object *);\n"; 05805 // @synchronized hooks. 05806 Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter( struct objc_object *);\n"; 05807 Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit( struct objc_object *);\n"; 05808 Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; 05809 Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; 05810 Preamble += "struct __objcFastEnumerationState {\n\t"; 05811 Preamble += "unsigned long state;\n\t"; 05812 Preamble += "void **itemsPtr;\n\t"; 05813 Preamble += "unsigned long *mutationsPtr;\n\t"; 05814 Preamble += "unsigned long extra[5];\n};\n"; 05815 Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; 05816 Preamble += "#define __FASTENUMERATIONSTATE\n"; 05817 Preamble += "#endif\n"; 05818 Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; 05819 Preamble += "struct __NSConstantStringImpl {\n"; 05820 Preamble += " int *isa;\n"; 05821 Preamble += " int flags;\n"; 05822 Preamble += " char *str;\n"; 05823 Preamble += " long length;\n"; 05824 Preamble += "};\n"; 05825 Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; 05826 Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; 05827 Preamble += "#else\n"; 05828 Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; 05829 Preamble += "#endif\n"; 05830 Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; 05831 Preamble += "#endif\n"; 05832 // Blocks preamble. 05833 Preamble += "#ifndef BLOCK_IMPL\n"; 05834 Preamble += "#define BLOCK_IMPL\n"; 05835 Preamble += "struct __block_impl {\n"; 05836 Preamble += " void *isa;\n"; 05837 Preamble += " int Flags;\n"; 05838 Preamble += " int Reserved;\n"; 05839 Preamble += " void *FuncPtr;\n"; 05840 Preamble += "};\n"; 05841 Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; 05842 Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; 05843 Preamble += "extern \"C\" __declspec(dllexport) " 05844 "void _Block_object_assign(void *, const void *, const int);\n"; 05845 Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; 05846 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; 05847 Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; 05848 Preamble += "#else\n"; 05849 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; 05850 Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; 05851 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; 05852 Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; 05853 Preamble += "#endif\n"; 05854 Preamble += "#endif\n"; 05855 if (LangOpts.MicrosoftExt) { 05856 Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; 05857 Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; 05858 Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. 05859 Preamble += "#define __attribute__(X)\n"; 05860 Preamble += "#endif\n"; 05861 Preamble += "#ifndef __weak\n"; 05862 Preamble += "#define __weak\n"; 05863 Preamble += "#endif\n"; 05864 Preamble += "#ifndef __block\n"; 05865 Preamble += "#define __block\n"; 05866 Preamble += "#endif\n"; 05867 } 05868 else { 05869 Preamble += "#define __block\n"; 05870 Preamble += "#define __weak\n"; 05871 } 05872 05873 // Declarations required for modern objective-c array and dictionary literals. 05874 Preamble += "\n#include <stdarg.h>\n"; 05875 Preamble += "struct __NSContainer_literal {\n"; 05876 Preamble += " void * *arr;\n"; 05877 Preamble += " __NSContainer_literal (unsigned int count, ...) {\n"; 05878 Preamble += "\tva_list marker;\n"; 05879 Preamble += "\tva_start(marker, count);\n"; 05880 Preamble += "\tarr = new void *[count];\n"; 05881 Preamble += "\tfor (unsigned i = 0; i < count; i++)\n"; 05882 Preamble += "\t arr[i] = va_arg(marker, void *);\n"; 05883 Preamble += "\tva_end( marker );\n"; 05884 Preamble += " };\n"; 05885 Preamble += " ~__NSContainer_literal() {\n"; 05886 Preamble += "\tdelete[] arr;\n"; 05887 Preamble += " }\n"; 05888 Preamble += "};\n"; 05889 05890 // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long 05891 // as this avoids warning in any 64bit/32bit compilation model. 05892 Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; 05893 } 05894 05895 /// RewriteIvarOffsetComputation - This rutine synthesizes computation of 05896 /// ivar offset. 05897 void RewriteModernObjC::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, 05898 std::string &Result) { 05899 if (ivar->isBitField()) { 05900 // FIXME: The hack below doesn't work for bitfields. For now, we simply 05901 // place all bitfields at offset 0. 05902 Result += "0"; 05903 } else { 05904 Result += "__OFFSETOFIVAR__(struct "; 05905 Result += ivar->getContainingInterface()->getNameAsString(); 05906 if (LangOpts.MicrosoftExt) 05907 Result += "_IMPL"; 05908 Result += ", "; 05909 Result += ivar->getNameAsString(); 05910 Result += ")"; 05911 } 05912 } 05913 05914 /// WriteModernMetadataDeclarations - Writes out metadata declarations for modern ABI. 05915 /// struct _prop_t { 05916 /// const char *name; 05917 /// char *attributes; 05918 /// } 05919 05920 /// struct _prop_list_t { 05921 /// uint32_t entsize; // sizeof(struct _prop_t) 05922 /// uint32_t count_of_properties; 05923 /// struct _prop_t prop_list[count_of_properties]; 05924 /// } 05925 05926 /// struct _protocol_t; 05927 05928 /// struct _protocol_list_t { 05929 /// long protocol_count; // Note, this is 32/64 bit 05930 /// struct _protocol_t * protocol_list[protocol_count]; 05931 /// } 05932 05933 /// struct _objc_method { 05934 /// SEL _cmd; 05935 /// const char *method_type; 05936 /// char *_imp; 05937 /// } 05938 05939 /// struct _method_list_t { 05940 /// uint32_t entsize; // sizeof(struct _objc_method) 05941 /// uint32_t method_count; 05942 /// struct _objc_method method_list[method_count]; 05943 /// } 05944 05945 /// struct _protocol_t { 05946 /// id isa; // NULL 05947 /// const char *protocol_name; 05948 /// const struct _protocol_list_t * protocol_list; // super protocols 05949 /// const struct method_list_t *instance_methods; 05950 /// const struct method_list_t *class_methods; 05951 /// const struct method_list_t *optionalInstanceMethods; 05952 /// const struct method_list_t *optionalClassMethods; 05953 /// const struct _prop_list_t * properties; 05954 /// const uint32_t size; // sizeof(struct _protocol_t) 05955 /// const uint32_t flags; // = 0 05956 /// const char ** extendedMethodTypes; 05957 /// } 05958 05959 /// struct _ivar_t { 05960 /// unsigned long int *offset; // pointer to ivar offset location 05961 /// const char *name; 05962 /// const char *type; 05963 /// uint32_t alignment; 05964 /// uint32_t size; 05965 /// } 05966 05967 /// struct _ivar_list_t { 05968 /// uint32 entsize; // sizeof(struct _ivar_t) 05969 /// uint32 count; 05970 /// struct _ivar_t list[count]; 05971 /// } 05972 05973 /// struct _class_ro_t { 05974 /// uint32_t flags; 05975 /// uint32_t instanceStart; 05976 /// uint32_t instanceSize; 05977 /// uint32_t reserved; // only when building for 64bit targets 05978 /// const uint8_t *ivarLayout; 05979 /// const char *name; 05980 /// const struct _method_list_t *baseMethods; 05981 /// const struct _protocol_list_t *baseProtocols; 05982 /// const struct _ivar_list_t *ivars; 05983 /// const uint8_t *weakIvarLayout; 05984 /// const struct _prop_list_t *properties; 05985 /// } 05986 05987 /// struct _class_t { 05988 /// struct _class_t *isa; 05989 /// struct _class_t *superclass; 05990 /// void *cache; 05991 /// IMP *vtable; 05992 /// struct _class_ro_t *ro; 05993 /// } 05994 05995 /// struct _category_t { 05996 /// const char *name; 05997 /// struct _class_t *cls; 05998 /// const struct _method_list_t *instance_methods; 05999 /// const struct _method_list_t *class_methods; 06000 /// const struct _protocol_list_t *protocols; 06001 /// const struct _prop_list_t *properties; 06002 /// } 06003 06004 /// MessageRefTy - LLVM for: 06005 /// struct _message_ref_t { 06006 /// IMP messenger; 06007 /// SEL name; 06008 /// }; 06009 06010 /// SuperMessageRefTy - LLVM for: 06011 /// struct _super_message_ref_t { 06012 /// SUPER_IMP messenger; 06013 /// SEL name; 06014 /// }; 06015 06016 static void WriteModernMetadataDeclarations(ASTContext *Context, std::string &Result) { 06017 static bool meta_data_declared = false; 06018 if (meta_data_declared) 06019 return; 06020 06021 Result += "\nstruct _prop_t {\n"; 06022 Result += "\tconst char *name;\n"; 06023 Result += "\tconst char *attributes;\n"; 06024 Result += "};\n"; 06025 06026 Result += "\nstruct _protocol_t;\n"; 06027 06028 Result += "\nstruct _objc_method {\n"; 06029 Result += "\tstruct objc_selector * _cmd;\n"; 06030 Result += "\tconst char *method_type;\n"; 06031 Result += "\tvoid *_imp;\n"; 06032 Result += "};\n"; 06033 06034 Result += "\nstruct _protocol_t {\n"; 06035 Result += "\tvoid * isa; // NULL\n"; 06036 Result += "\tconst char *protocol_name;\n"; 06037 Result += "\tconst struct _protocol_list_t * protocol_list; // super protocols\n"; 06038 Result += "\tconst struct method_list_t *instance_methods;\n"; 06039 Result += "\tconst struct method_list_t *class_methods;\n"; 06040 Result += "\tconst struct method_list_t *optionalInstanceMethods;\n"; 06041 Result += "\tconst struct method_list_t *optionalClassMethods;\n"; 06042 Result += "\tconst struct _prop_list_t * properties;\n"; 06043 Result += "\tconst unsigned int size; // sizeof(struct _protocol_t)\n"; 06044 Result += "\tconst unsigned int flags; // = 0\n"; 06045 Result += "\tconst char ** extendedMethodTypes;\n"; 06046 Result += "};\n"; 06047 06048 Result += "\nstruct _ivar_t {\n"; 06049 Result += "\tunsigned long int *offset; // pointer to ivar offset location\n"; 06050 Result += "\tconst char *name;\n"; 06051 Result += "\tconst char *type;\n"; 06052 Result += "\tunsigned int alignment;\n"; 06053 Result += "\tunsigned int size;\n"; 06054 Result += "};\n"; 06055 06056 Result += "\nstruct _class_ro_t {\n"; 06057 Result += "\tunsigned int flags;\n"; 06058 Result += "\tunsigned int instanceStart;\n"; 06059 Result += "\tunsigned int instanceSize;\n"; 06060 const llvm::Triple &Triple(Context->getTargetInfo().getTriple()); 06061 if (Triple.getArch() == llvm::Triple::x86_64) 06062 Result += "\tunsigned int reserved;\n"; 06063 Result += "\tconst unsigned char *ivarLayout;\n"; 06064 Result += "\tconst char *name;\n"; 06065 Result += "\tconst struct _method_list_t *baseMethods;\n"; 06066 Result += "\tconst struct _objc_protocol_list *baseProtocols;\n"; 06067 Result += "\tconst struct _ivar_list_t *ivars;\n"; 06068 Result += "\tconst unsigned char *weakIvarLayout;\n"; 06069 Result += "\tconst struct _prop_list_t *properties;\n"; 06070 Result += "};\n"; 06071 06072 Result += "\nstruct _class_t {\n"; 06073 Result += "\tstruct _class_t *isa;\n"; 06074 Result += "\tstruct _class_t *superclass;\n"; 06075 Result += "\tvoid *cache;\n"; 06076 Result += "\tvoid *vtable;\n"; 06077 Result += "\tstruct _class_ro_t *ro;\n"; 06078 Result += "};\n"; 06079 06080 Result += "\nstruct _category_t {\n"; 06081 Result += "\tconst char *name;\n"; 06082 Result += "\tstruct _class_t *cls;\n"; 06083 Result += "\tconst struct _method_list_t *instance_methods;\n"; 06084 Result += "\tconst struct _method_list_t *class_methods;\n"; 06085 Result += "\tconst struct _protocol_list_t *protocols;\n"; 06086 Result += "\tconst struct _prop_list_t *properties;\n"; 06087 Result += "};\n"; 06088 06089 Result += "extern \"C\" __declspec(dllimport) struct objc_cache _objc_empty_cache;\n"; 06090 Result += "#pragma warning(disable:4273)\n"; 06091 meta_data_declared = true; 06092 } 06093 06094 static void Write_protocol_list_t_TypeDecl(std::string &Result, 06095 long super_protocol_count) { 06096 Result += "struct /*_protocol_list_t*/"; Result += " {\n"; 06097 Result += "\tlong protocol_count; // Note, this is 32/64 bit\n"; 06098 Result += "\tstruct _protocol_t *super_protocols["; 06099 Result += utostr(super_protocol_count); Result += "];\n"; 06100 Result += "}"; 06101 } 06102 06103 static void Write_method_list_t_TypeDecl(std::string &Result, 06104 unsigned int method_count) { 06105 Result += "struct /*_method_list_t*/"; Result += " {\n"; 06106 Result += "\tunsigned int entsize; // sizeof(struct _objc_method)\n"; 06107 Result += "\tunsigned int method_count;\n"; 06108 Result += "\tstruct _objc_method method_list["; 06109 Result += utostr(method_count); Result += "];\n"; 06110 Result += "}"; 06111 } 06112 06113 static void Write__prop_list_t_TypeDecl(std::string &Result, 06114 unsigned int property_count) { 06115 Result += "struct /*_prop_list_t*/"; Result += " {\n"; 06116 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n"; 06117 Result += "\tunsigned int count_of_properties;\n"; 06118 Result += "\tstruct _prop_t prop_list["; 06119 Result += utostr(property_count); Result += "];\n"; 06120 Result += "}"; 06121 } 06122 06123 static void Write__ivar_list_t_TypeDecl(std::string &Result, 06124 unsigned int ivar_count) { 06125 Result += "struct /*_ivar_list_t*/"; Result += " {\n"; 06126 Result += "\tunsigned int entsize; // sizeof(struct _prop_t)\n"; 06127 Result += "\tunsigned int count;\n"; 06128 Result += "\tstruct _ivar_t ivar_list["; 06129 Result += utostr(ivar_count); Result += "];\n"; 06130 Result += "}"; 06131 } 06132 06133 static void Write_protocol_list_initializer(ASTContext *Context, std::string &Result, 06134 ArrayRef<ObjCProtocolDecl *> SuperProtocols, 06135 StringRef VarName, 06136 StringRef ProtocolName) { 06137 if (SuperProtocols.size() > 0) { 06138 Result += "\nstatic "; 06139 Write_protocol_list_t_TypeDecl(Result, SuperProtocols.size()); 06140 Result += " "; Result += VarName; 06141 Result += ProtocolName; 06142 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 06143 Result += "\t"; Result += utostr(SuperProtocols.size()); Result += ",\n"; 06144 for (unsigned i = 0, e = SuperProtocols.size(); i < e; i++) { 06145 ObjCProtocolDecl *SuperPD = SuperProtocols[i]; 06146 Result += "\t&"; Result += "_OBJC_PROTOCOL_"; 06147 Result += SuperPD->getNameAsString(); 06148 if (i == e-1) 06149 Result += "\n};\n"; 06150 else 06151 Result += ",\n"; 06152 } 06153 } 06154 } 06155 06156 static void Write_method_list_t_initializer(RewriteModernObjC &RewriteObj, 06157 ASTContext *Context, std::string &Result, 06158 ArrayRef<ObjCMethodDecl *> Methods, 06159 StringRef VarName, 06160 StringRef TopLevelDeclName, 06161 bool MethodImpl) { 06162 if (Methods.size() > 0) { 06163 Result += "\nstatic "; 06164 Write_method_list_t_TypeDecl(Result, Methods.size()); 06165 Result += " "; Result += VarName; 06166 Result += TopLevelDeclName; 06167 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 06168 Result += "\t"; Result += "sizeof(_objc_method)"; Result += ",\n"; 06169 Result += "\t"; Result += utostr(Methods.size()); Result += ",\n"; 06170 for (unsigned i = 0, e = Methods.size(); i < e; i++) { 06171 ObjCMethodDecl *MD = Methods[i]; 06172 if (i == 0) 06173 Result += "\t{{(struct objc_selector *)\""; 06174 else 06175 Result += "\t{(struct objc_selector *)\""; 06176 Result += (MD)->getSelector().getAsString(); Result += "\""; 06177 Result += ", "; 06178 std::string MethodTypeString; 06179 Context->getObjCEncodingForMethodDecl(MD, MethodTypeString); 06180 Result += "\""; Result += MethodTypeString; Result += "\""; 06181 Result += ", "; 06182 if (!MethodImpl) 06183 Result += "0"; 06184 else { 06185 Result += "(void *)"; 06186 Result += RewriteObj.MethodInternalNames[MD]; 06187 } 06188 if (i == e-1) 06189 Result += "}}\n"; 06190 else 06191 Result += "},\n"; 06192 } 06193 Result += "};\n"; 06194 } 06195 } 06196 06197 static void Write_prop_list_t_initializer(RewriteModernObjC &RewriteObj, 06198 ASTContext *Context, std::string &Result, 06199 ArrayRef<ObjCPropertyDecl *> Properties, 06200 const Decl *Container, 06201 StringRef VarName, 06202 StringRef ProtocolName) { 06203 if (Properties.size() > 0) { 06204 Result += "\nstatic "; 06205 Write__prop_list_t_TypeDecl(Result, Properties.size()); 06206 Result += " "; Result += VarName; 06207 Result += ProtocolName; 06208 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 06209 Result += "\t"; Result += "sizeof(_prop_t)"; Result += ",\n"; 06210 Result += "\t"; Result += utostr(Properties.size()); Result += ",\n"; 06211 for (unsigned i = 0, e = Properties.size(); i < e; i++) { 06212 ObjCPropertyDecl *PropDecl = Properties[i]; 06213 if (i == 0) 06214 Result += "\t{{\""; 06215 else 06216 Result += "\t{\""; 06217 Result += PropDecl->getName(); Result += "\","; 06218 std::string PropertyTypeString, QuotePropertyTypeString; 06219 Context->getObjCEncodingForPropertyDecl(PropDecl, Container, PropertyTypeString); 06220 RewriteObj.QuoteDoublequotes(PropertyTypeString, QuotePropertyTypeString); 06221 Result += "\""; Result += QuotePropertyTypeString; Result += "\""; 06222 if (i == e-1) 06223 Result += "}}\n"; 06224 else 06225 Result += "},\n"; 06226 } 06227 Result += "};\n"; 06228 } 06229 } 06230 06231 // Metadata flags 06232 enum MetaDataDlags { 06233 CLS = 0x0, 06234 CLS_META = 0x1, 06235 CLS_ROOT = 0x2, 06236 OBJC2_CLS_HIDDEN = 0x10, 06237 CLS_EXCEPTION = 0x20, 06238 06239 /// (Obsolete) ARC-specific: this class has a .release_ivars method 06240 CLS_HAS_IVAR_RELEASER = 0x40, 06241 /// class was compiled with -fobjc-arr 06242 CLS_COMPILED_BY_ARC = 0x80 // (1<<7) 06243 }; 06244 06245 static void Write__class_ro_t_initializer(ASTContext *Context, std::string &Result, 06246 unsigned int flags, 06247 const std::string &InstanceStart, 06248 const std::string &InstanceSize, 06249 ArrayRef<ObjCMethodDecl *>baseMethods, 06250 ArrayRef<ObjCProtocolDecl *>baseProtocols, 06251 ArrayRef<ObjCIvarDecl *>ivars, 06252 ArrayRef<ObjCPropertyDecl *>Properties, 06253 StringRef VarName, 06254 StringRef ClassName) { 06255 Result += "\nstatic struct _class_ro_t "; 06256 Result += VarName; Result += ClassName; 06257 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 06258 Result += "\t"; 06259 Result += llvm::utostr(flags); Result += ", "; 06260 Result += InstanceStart; Result += ", "; 06261 Result += InstanceSize; Result += ", \n"; 06262 Result += "\t"; 06263 const llvm::Triple &Triple(Context->getTargetInfo().getTriple()); 06264 if (Triple.getArch() == llvm::Triple::x86_64) 06265 // uint32_t const reserved; // only when building for 64bit targets 06266 Result += "(unsigned int)0, \n\t"; 06267 // const uint8_t * const ivarLayout; 06268 Result += "0, \n\t"; 06269 Result += "\""; Result += ClassName; Result += "\",\n\t"; 06270 bool metaclass = ((flags & CLS_META) != 0); 06271 if (baseMethods.size() > 0) { 06272 Result += "(const struct _method_list_t *)&"; 06273 if (metaclass) 06274 Result += "_OBJC_$_CLASS_METHODS_"; 06275 else 06276 Result += "_OBJC_$_INSTANCE_METHODS_"; 06277 Result += ClassName; 06278 Result += ",\n\t"; 06279 } 06280 else 06281 Result += "0, \n\t"; 06282 06283 if (!metaclass && baseProtocols.size() > 0) { 06284 Result += "(const struct _objc_protocol_list *)&"; 06285 Result += "_OBJC_CLASS_PROTOCOLS_$_"; Result += ClassName; 06286 Result += ",\n\t"; 06287 } 06288 else 06289 Result += "0, \n\t"; 06290 06291 if (!metaclass && ivars.size() > 0) { 06292 Result += "(const struct _ivar_list_t *)&"; 06293 Result += "_OBJC_$_INSTANCE_VARIABLES_"; Result += ClassName; 06294 Result += ",\n\t"; 06295 } 06296 else 06297 Result += "0, \n\t"; 06298 06299 // weakIvarLayout 06300 Result += "0, \n\t"; 06301 if (!metaclass && Properties.size() > 0) { 06302 Result += "(const struct _prop_list_t *)&"; 06303 Result += "_OBJC_$_PROP_LIST_"; Result += ClassName; 06304 Result += ",\n"; 06305 } 06306 else 06307 Result += "0, \n"; 06308 06309 Result += "};\n"; 06310 } 06311 06312 static void Write_class_t(ASTContext *Context, std::string &Result, 06313 StringRef VarName, 06314 const ObjCInterfaceDecl *CDecl, bool metaclass) { 06315 bool rootClass = (!CDecl->getSuperClass()); 06316 const ObjCInterfaceDecl *RootClass = CDecl; 06317 06318 if (!rootClass) { 06319 // Find the Root class 06320 RootClass = CDecl->getSuperClass(); 06321 while (RootClass->getSuperClass()) { 06322 RootClass = RootClass->getSuperClass(); 06323 } 06324 } 06325 06326 if (metaclass && rootClass) { 06327 // Need to handle a case of use of forward declaration. 06328 Result += "\n"; 06329 Result += "extern \"C\" "; 06330 if (CDecl->getImplementation()) 06331 Result += "__declspec(dllexport) "; 06332 else 06333 Result += "__declspec(dllimport) "; 06334 06335 Result += "struct _class_t OBJC_CLASS_$_"; 06336 Result += CDecl->getNameAsString(); 06337 Result += ";\n"; 06338 } 06339 // Also, for possibility of 'super' metadata class not having been defined yet. 06340 if (!rootClass) { 06341 ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); 06342 Result += "\n"; 06343 Result += "extern \"C\" "; 06344 if (SuperClass->getImplementation()) 06345 Result += "__declspec(dllexport) "; 06346 else 06347 Result += "__declspec(dllimport) "; 06348 06349 Result += "struct _class_t "; 06350 Result += VarName; 06351 Result += SuperClass->getNameAsString(); 06352 Result += ";\n"; 06353 06354 if (metaclass && RootClass != SuperClass) { 06355 Result += "extern \"C\" "; 06356 if (RootClass->getImplementation()) 06357 Result += "__declspec(dllexport) "; 06358 else 06359 Result += "__declspec(dllimport) "; 06360 06361 Result += "struct _class_t "; 06362 Result += VarName; 06363 Result += RootClass->getNameAsString(); 06364 Result += ";\n"; 06365 } 06366 } 06367 06368 Result += "\nextern \"C\" __declspec(dllexport) struct _class_t "; 06369 Result += VarName; Result += CDecl->getNameAsString(); 06370 Result += " __attribute__ ((used, section (\"__DATA,__objc_data\"))) = {\n"; 06371 Result += "\t"; 06372 if (metaclass) { 06373 if (!rootClass) { 06374 Result += "0, // &"; Result += VarName; 06375 Result += RootClass->getNameAsString(); 06376 Result += ",\n\t"; 06377 Result += "0, // &"; Result += VarName; 06378 Result += CDecl->getSuperClass()->getNameAsString(); 06379 Result += ",\n\t"; 06380 } 06381 else { 06382 Result += "0, // &"; Result += VarName; 06383 Result += CDecl->getNameAsString(); 06384 Result += ",\n\t"; 06385 Result += "0, // &OBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 06386 Result += ",\n\t"; 06387 } 06388 } 06389 else { 06390 Result += "0, // &OBJC_METACLASS_$_"; 06391 Result += CDecl->getNameAsString(); 06392 Result += ",\n\t"; 06393 if (!rootClass) { 06394 Result += "0, // &"; Result += VarName; 06395 Result += CDecl->getSuperClass()->getNameAsString(); 06396 Result += ",\n\t"; 06397 } 06398 else 06399 Result += "0,\n\t"; 06400 } 06401 Result += "0, // (void *)&_objc_empty_cache,\n\t"; 06402 Result += "0, // unused, was (void *)&_objc_empty_vtable,\n\t"; 06403 if (metaclass) 06404 Result += "&_OBJC_METACLASS_RO_$_"; 06405 else 06406 Result += "&_OBJC_CLASS_RO_$_"; 06407 Result += CDecl->getNameAsString(); 06408 Result += ",\n};\n"; 06409 06410 // Add static function to initialize some of the meta-data fields. 06411 // avoid doing it twice. 06412 if (metaclass) 06413 return; 06414 06415 const ObjCInterfaceDecl *SuperClass = 06416 rootClass ? CDecl : CDecl->getSuperClass(); 06417 06418 Result += "static void OBJC_CLASS_SETUP_$_"; 06419 Result += CDecl->getNameAsString(); 06420 Result += "(void ) {\n"; 06421 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 06422 Result += ".isa = "; Result += "&OBJC_METACLASS_$_"; 06423 Result += RootClass->getNameAsString(); Result += ";\n"; 06424 06425 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 06426 Result += ".superclass = "; 06427 if (rootClass) 06428 Result += "&OBJC_CLASS_$_"; 06429 else 06430 Result += "&OBJC_METACLASS_$_"; 06431 06432 Result += SuperClass->getNameAsString(); Result += ";\n"; 06433 06434 Result += "\tOBJC_METACLASS_$_"; Result += CDecl->getNameAsString(); 06435 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n"; 06436 06437 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 06438 Result += ".isa = "; Result += "&OBJC_METACLASS_$_"; 06439 Result += CDecl->getNameAsString(); Result += ";\n"; 06440 06441 if (!rootClass) { 06442 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 06443 Result += ".superclass = "; Result += "&OBJC_CLASS_$_"; 06444 Result += SuperClass->getNameAsString(); Result += ";\n"; 06445 } 06446 06447 Result += "\tOBJC_CLASS_$_"; Result += CDecl->getNameAsString(); 06448 Result += ".cache = "; Result += "&_objc_empty_cache"; Result += ";\n"; 06449 Result += "}\n"; 06450 } 06451 06452 static void Write_category_t(RewriteModernObjC &RewriteObj, ASTContext *Context, 06453 std::string &Result, 06454 ObjCCategoryDecl *CatDecl, 06455 ObjCInterfaceDecl *ClassDecl, 06456 ArrayRef<ObjCMethodDecl *> InstanceMethods, 06457 ArrayRef<ObjCMethodDecl *> ClassMethods, 06458 ArrayRef<ObjCProtocolDecl *> RefedProtocols, 06459 ArrayRef<ObjCPropertyDecl *> ClassProperties) { 06460 StringRef CatName = CatDecl->getName(); 06461 StringRef ClassName = ClassDecl->getName(); 06462 // must declare an extern class object in case this class is not implemented 06463 // in this TU. 06464 Result += "\n"; 06465 Result += "extern \"C\" "; 06466 if (ClassDecl->getImplementation()) 06467 Result += "__declspec(dllexport) "; 06468 else 06469 Result += "__declspec(dllimport) "; 06470 06471 Result += "struct _class_t "; 06472 Result += "OBJC_CLASS_$_"; Result += ClassName; 06473 Result += ";\n"; 06474 06475 Result += "\nstatic struct _category_t "; 06476 Result += "_OBJC_$_CATEGORY_"; 06477 Result += ClassName; Result += "_$_"; Result += CatName; 06478 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n"; 06479 Result += "{\n"; 06480 Result += "\t\""; Result += ClassName; Result += "\",\n"; 06481 Result += "\t0, // &"; Result += "OBJC_CLASS_$_"; Result += ClassName; 06482 Result += ",\n"; 06483 if (InstanceMethods.size() > 0) { 06484 Result += "\t(const struct _method_list_t *)&"; 06485 Result += "_OBJC_$_CATEGORY_INSTANCE_METHODS_"; 06486 Result += ClassName; Result += "_$_"; Result += CatName; 06487 Result += ",\n"; 06488 } 06489 else 06490 Result += "\t0,\n"; 06491 06492 if (ClassMethods.size() > 0) { 06493 Result += "\t(const struct _method_list_t *)&"; 06494 Result += "_OBJC_$_CATEGORY_CLASS_METHODS_"; 06495 Result += ClassName; Result += "_$_"; Result += CatName; 06496 Result += ",\n"; 06497 } 06498 else 06499 Result += "\t0,\n"; 06500 06501 if (RefedProtocols.size() > 0) { 06502 Result += "\t(const struct _protocol_list_t *)&"; 06503 Result += "_OBJC_CATEGORY_PROTOCOLS_$_"; 06504 Result += ClassName; Result += "_$_"; Result += CatName; 06505 Result += ",\n"; 06506 } 06507 else 06508 Result += "\t0,\n"; 06509 06510 if (ClassProperties.size() > 0) { 06511 Result += "\t(const struct _prop_list_t *)&"; Result += "_OBJC_$_PROP_LIST_"; 06512 Result += ClassName; Result += "_$_"; Result += CatName; 06513 Result += ",\n"; 06514 } 06515 else 06516 Result += "\t0,\n"; 06517 06518 Result += "};\n"; 06519 06520 // Add static function to initialize the class pointer in the category structure. 06521 Result += "static void OBJC_CATEGORY_SETUP_$_"; 06522 Result += ClassDecl->getNameAsString(); 06523 Result += "_$_"; 06524 Result += CatName; 06525 Result += "(void ) {\n"; 06526 Result += "\t_OBJC_$_CATEGORY_"; 06527 Result += ClassDecl->getNameAsString(); 06528 Result += "_$_"; 06529 Result += CatName; 06530 Result += ".cls = "; Result += "&OBJC_CLASS_$_"; Result += ClassName; 06531 Result += ";\n}\n"; 06532 } 06533 06534 static void Write__extendedMethodTypes_initializer(RewriteModernObjC &RewriteObj, 06535 ASTContext *Context, std::string &Result, 06536 ArrayRef<ObjCMethodDecl *> Methods, 06537 StringRef VarName, 06538 StringRef ProtocolName) { 06539 if (Methods.size() == 0) 06540 return; 06541 06542 Result += "\nstatic const char *"; 06543 Result += VarName; Result += ProtocolName; 06544 Result += " [] __attribute__ ((used, section (\"__DATA,__objc_const\"))) = \n"; 06545 Result += "{\n"; 06546 for (unsigned i = 0, e = Methods.size(); i < e; i++) { 06547 ObjCMethodDecl *MD = Methods[i]; 06548 std::string MethodTypeString, QuoteMethodTypeString; 06549 Context->getObjCEncodingForMethodDecl(MD, MethodTypeString, true); 06550 RewriteObj.QuoteDoublequotes(MethodTypeString, QuoteMethodTypeString); 06551 Result += "\t\""; Result += QuoteMethodTypeString; Result += "\""; 06552 if (i == e-1) 06553 Result += "\n};\n"; 06554 else { 06555 Result += ",\n"; 06556 } 06557 } 06558 } 06559 06560 static void Write_IvarOffsetVar(RewriteModernObjC &RewriteObj, 06561 ASTContext *Context, 06562 std::string &Result, 06563 ArrayRef<ObjCIvarDecl *> Ivars, 06564 ObjCInterfaceDecl *CDecl) { 06565 // FIXME. visibilty of offset symbols may have to be set; for Darwin 06566 // this is what happens: 06567 /** 06568 if (Ivar->getAccessControl() == ObjCIvarDecl::Private || 06569 Ivar->getAccessControl() == ObjCIvarDecl::Package || 06570 Class->getVisibility() == HiddenVisibility) 06571 Visibility shoud be: HiddenVisibility; 06572 else 06573 Visibility shoud be: DefaultVisibility; 06574 */ 06575 06576 Result += "\n"; 06577 for (unsigned i =0, e = Ivars.size(); i < e; i++) { 06578 ObjCIvarDecl *IvarDecl = Ivars[i]; 06579 if (Context->getLangOpts().MicrosoftExt) 06580 Result += "__declspec(allocate(\".objc_ivar$B\")) "; 06581 06582 if (!Context->getLangOpts().MicrosoftExt || 06583 IvarDecl->getAccessControl() == ObjCIvarDecl::Private || 06584 IvarDecl->getAccessControl() == ObjCIvarDecl::Package) 06585 Result += "extern \"C\" unsigned long int "; 06586 else 06587 Result += "extern \"C\" __declspec(dllexport) unsigned long int "; 06588 WriteInternalIvarName(CDecl, IvarDecl, Result); 06589 Result += " __attribute__ ((used, section (\"__DATA,__objc_ivar\")))"; 06590 Result += " = "; 06591 RewriteObj.RewriteIvarOffsetComputation(IvarDecl, Result); 06592 Result += ";\n"; 06593 } 06594 } 06595 06596 static void Write__ivar_list_t_initializer(RewriteModernObjC &RewriteObj, 06597 ASTContext *Context, std::string &Result, 06598 ArrayRef<ObjCIvarDecl *> Ivars, 06599 StringRef VarName, 06600 ObjCInterfaceDecl *CDecl) { 06601 if (Ivars.size() > 0) { 06602 Write_IvarOffsetVar(RewriteObj, Context, Result, Ivars, CDecl); 06603 06604 Result += "\nstatic "; 06605 Write__ivar_list_t_TypeDecl(Result, Ivars.size()); 06606 Result += " "; Result += VarName; 06607 Result += CDecl->getNameAsString(); 06608 Result += " __attribute__ ((used, section (\"__DATA,__objc_const\"))) = {\n"; 06609 Result += "\t"; Result += "sizeof(_ivar_t)"; Result += ",\n"; 06610 Result += "\t"; Result += utostr(Ivars.size()); Result += ",\n"; 06611 for (unsigned i =0, e = Ivars.size(); i < e; i++) { 06612 ObjCIvarDecl *IvarDecl = Ivars[i]; 06613 if (i == 0) 06614 Result += "\t{{"; 06615 else 06616 Result += "\t {"; 06617 Result += "(unsigned long int *)&"; 06618 WriteInternalIvarName(CDecl, IvarDecl, Result); 06619 Result += ", "; 06620 06621 Result += "\""; Result += IvarDecl->getName(); Result += "\", "; 06622 std::string IvarTypeString, QuoteIvarTypeString; 06623 Context->getObjCEncodingForType(IvarDecl->getType(), IvarTypeString, 06624 IvarDecl); 06625 RewriteObj.QuoteDoublequotes(IvarTypeString, QuoteIvarTypeString); 06626 Result += "\""; Result += QuoteIvarTypeString; Result += "\", "; 06627 06628 // FIXME. this alignment represents the host alignment and need be changed to 06629 // represent the target alignment. 06630 unsigned Align = Context->getTypeAlign(IvarDecl->getType())/8; 06631 Align = llvm::Log2_32(Align); 06632 Result += llvm::utostr(Align); Result += ", "; 06633 CharUnits Size = Context->getTypeSizeInChars(IvarDecl->getType()); 06634 Result += llvm::utostr(Size.getQuantity()); 06635 if (i == e-1) 06636 Result += "}}\n"; 06637 else 06638 Result += "},\n"; 06639 } 06640 Result += "};\n"; 06641 } 06642 } 06643 06644 /// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. 06645 void RewriteModernObjC::RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, 06646 std::string &Result) { 06647 06648 // Do not synthesize the protocol more than once. 06649 if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl())) 06650 return; 06651 WriteModernMetadataDeclarations(Context, Result); 06652 06653 if (ObjCProtocolDecl *Def = PDecl->getDefinition()) 06654 PDecl = Def; 06655 // Must write out all protocol definitions in current qualifier list, 06656 // and in their nested qualifiers before writing out current definition. 06657 for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), 06658 E = PDecl->protocol_end(); I != E; ++I) 06659 RewriteObjCProtocolMetaData(*I, Result); 06660 06661 // Construct method lists. 06662 std::vector<ObjCMethodDecl *> InstanceMethods, ClassMethods; 06663 std::vector<ObjCMethodDecl *> OptInstanceMethods, OptClassMethods; 06664 for (ObjCProtocolDecl::instmeth_iterator 06665 I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); 06666 I != E; ++I) { 06667 ObjCMethodDecl *MD = *I; 06668 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 06669 OptInstanceMethods.push_back(MD); 06670 } else { 06671 InstanceMethods.push_back(MD); 06672 } 06673 } 06674 06675 for (ObjCProtocolDecl::classmeth_iterator 06676 I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); 06677 I != E; ++I) { 06678 ObjCMethodDecl *MD = *I; 06679 if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { 06680 OptClassMethods.push_back(MD); 06681 } else { 06682 ClassMethods.push_back(MD); 06683 } 06684 } 06685 std::vector<ObjCMethodDecl *> AllMethods; 06686 for (unsigned i = 0, e = InstanceMethods.size(); i < e; i++) 06687 AllMethods.push_back(InstanceMethods[i]); 06688 for (unsigned i = 0, e = ClassMethods.size(); i < e; i++) 06689 AllMethods.push_back(ClassMethods[i]); 06690 for (unsigned i = 0, e = OptInstanceMethods.size(); i < e; i++) 06691 AllMethods.push_back(OptInstanceMethods[i]); 06692 for (unsigned i = 0, e = OptClassMethods.size(); i < e; i++) 06693 AllMethods.push_back(OptClassMethods[i]); 06694 06695 Write__extendedMethodTypes_initializer(*this, Context, Result, 06696 AllMethods, 06697 "_OBJC_PROTOCOL_METHOD_TYPES_", 06698 PDecl->getNameAsString()); 06699 // Protocol's super protocol list 06700 std::vector<ObjCProtocolDecl *> SuperProtocols; 06701 for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), 06702 E = PDecl->protocol_end(); I != E; ++I) 06703 SuperProtocols.push_back(*I); 06704 06705 Write_protocol_list_initializer(Context, Result, SuperProtocols, 06706 "_OBJC_PROTOCOL_REFS_", 06707 PDecl->getNameAsString()); 06708 06709 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 06710 "_OBJC_PROTOCOL_INSTANCE_METHODS_", 06711 PDecl->getNameAsString(), false); 06712 06713 Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 06714 "_OBJC_PROTOCOL_CLASS_METHODS_", 06715 PDecl->getNameAsString(), false); 06716 06717 Write_method_list_t_initializer(*this, Context, Result, OptInstanceMethods, 06718 "_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_", 06719 PDecl->getNameAsString(), false); 06720 06721 Write_method_list_t_initializer(*this, Context, Result, OptClassMethods, 06722 "_OBJC_PROTOCOL_OPT_CLASS_METHODS_", 06723 PDecl->getNameAsString(), false); 06724 06725 // Protocol's property metadata. 06726 std::vector<ObjCPropertyDecl *> ProtocolProperties; 06727 for (ObjCContainerDecl::prop_iterator I = PDecl->prop_begin(), 06728 E = PDecl->prop_end(); I != E; ++I) 06729 ProtocolProperties.push_back(&*I); 06730 06731 Write_prop_list_t_initializer(*this, Context, Result, ProtocolProperties, 06732 /* Container */0, 06733 "_OBJC_PROTOCOL_PROPERTIES_", 06734 PDecl->getNameAsString()); 06735 06736 // Writer out root metadata for current protocol: struct _protocol_t 06737 Result += "\n"; 06738 if (LangOpts.MicrosoftExt) 06739 Result += "static "; 06740 Result += "struct _protocol_t _OBJC_PROTOCOL_"; 06741 Result += PDecl->getNameAsString(); 06742 Result += " __attribute__ ((used, section (\"__DATA,__datacoal_nt,coalesced\"))) = {\n"; 06743 Result += "\t0,\n"; // id is; is null 06744 Result += "\t\""; Result += PDecl->getNameAsString(); Result += "\",\n"; 06745 if (SuperProtocols.size() > 0) { 06746 Result += "\t(const struct _protocol_list_t *)&"; Result += "_OBJC_PROTOCOL_REFS_"; 06747 Result += PDecl->getNameAsString(); Result += ",\n"; 06748 } 06749 else 06750 Result += "\t0,\n"; 06751 if (InstanceMethods.size() > 0) { 06752 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; 06753 Result += PDecl->getNameAsString(); Result += ",\n"; 06754 } 06755 else 06756 Result += "\t0,\n"; 06757 06758 if (ClassMethods.size() > 0) { 06759 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_CLASS_METHODS_"; 06760 Result += PDecl->getNameAsString(); Result += ",\n"; 06761 } 06762 else 06763 Result += "\t0,\n"; 06764 06765 if (OptInstanceMethods.size() > 0) { 06766 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_INSTANCE_METHODS_"; 06767 Result += PDecl->getNameAsString(); Result += ",\n"; 06768 } 06769 else 06770 Result += "\t0,\n"; 06771 06772 if (OptClassMethods.size() > 0) { 06773 Result += "\t(const struct method_list_t *)&_OBJC_PROTOCOL_OPT_CLASS_METHODS_"; 06774 Result += PDecl->getNameAsString(); Result += ",\n"; 06775 } 06776 else 06777 Result += "\t0,\n"; 06778 06779 if (ProtocolProperties.size() > 0) { 06780 Result += "\t(const struct _prop_list_t *)&_OBJC_PROTOCOL_PROPERTIES_"; 06781 Result += PDecl->getNameAsString(); Result += ",\n"; 06782 } 06783 else 06784 Result += "\t0,\n"; 06785 06786 Result += "\t"; Result += "sizeof(_protocol_t)"; Result += ",\n"; 06787 Result += "\t0,\n"; 06788 06789 if (AllMethods.size() > 0) { 06790 Result += "\t(const char **)&"; Result += "_OBJC_PROTOCOL_METHOD_TYPES_"; 06791 Result += PDecl->getNameAsString(); 06792 Result += "\n};\n"; 06793 } 06794 else 06795 Result += "\t0\n};\n"; 06796 06797 if (LangOpts.MicrosoftExt) 06798 Result += "static "; 06799 Result += "struct _protocol_t *"; 06800 Result += "_OBJC_LABEL_PROTOCOL_$_"; Result += PDecl->getNameAsString(); 06801 Result += " = &_OBJC_PROTOCOL_"; Result += PDecl->getNameAsString(); 06802 Result += ";\n"; 06803 06804 // Mark this protocol as having been generated. 06805 if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl())) 06806 llvm_unreachable("protocol already synthesized"); 06807 06808 } 06809 06810 void RewriteModernObjC::RewriteObjCProtocolListMetaData( 06811 const ObjCList<ObjCProtocolDecl> &Protocols, 06812 StringRef prefix, StringRef ClassName, 06813 std::string &Result) { 06814 if (Protocols.empty()) return; 06815 06816 for (unsigned i = 0; i != Protocols.size(); i++) 06817 RewriteObjCProtocolMetaData(Protocols[i], Result); 06818 06819 // Output the top lovel protocol meta-data for the class. 06820 /* struct _objc_protocol_list { 06821 struct _objc_protocol_list *next; 06822 int protocol_count; 06823 struct _objc_protocol *class_protocols[]; 06824 } 06825 */ 06826 Result += "\n"; 06827 if (LangOpts.MicrosoftExt) 06828 Result += "__declspec(allocate(\".cat_cls_meth$B\")) "; 06829 Result += "static struct {\n"; 06830 Result += "\tstruct _objc_protocol_list *next;\n"; 06831 Result += "\tint protocol_count;\n"; 06832 Result += "\tstruct _objc_protocol *class_protocols["; 06833 Result += utostr(Protocols.size()); 06834 Result += "];\n} _OBJC_"; 06835 Result += prefix; 06836 Result += "_PROTOCOLS_"; 06837 Result += ClassName; 06838 Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " 06839 "{\n\t0, "; 06840 Result += utostr(Protocols.size()); 06841 Result += "\n"; 06842 06843 Result += "\t,{&_OBJC_PROTOCOL_"; 06844 Result += Protocols[0]->getNameAsString(); 06845 Result += " \n"; 06846 06847 for (unsigned i = 1; i != Protocols.size(); i++) { 06848 Result += "\t ,&_OBJC_PROTOCOL_"; 06849 Result += Protocols[i]->getNameAsString(); 06850 Result += "\n"; 06851 } 06852 Result += "\t }\n};\n"; 06853 } 06854 06855 /// hasObjCExceptionAttribute - Return true if this class or any super 06856 /// class has the __objc_exception__ attribute. 06857 /// FIXME. Move this to ASTContext.cpp as it is also used for IRGen. 06858 static bool hasObjCExceptionAttribute(ASTContext &Context, 06859 const ObjCInterfaceDecl *OID) { 06860 if (OID->hasAttr<ObjCExceptionAttr>()) 06861 return true; 06862 if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) 06863 return hasObjCExceptionAttribute(Context, Super); 06864 return false; 06865 } 06866 06867 void RewriteModernObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, 06868 std::string &Result) { 06869 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 06870 06871 // Explicitly declared @interface's are already synthesized. 06872 if (CDecl->isImplicitInterfaceDecl()) 06873 assert(false && 06874 "Legacy implicit interface rewriting not supported in moder abi"); 06875 06876 WriteModernMetadataDeclarations(Context, Result); 06877 SmallVector<ObjCIvarDecl *, 8> IVars; 06878 06879 for (ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 06880 IVD; IVD = IVD->getNextIvar()) { 06881 // Ignore unnamed bit-fields. 06882 if (!IVD->getDeclName()) 06883 continue; 06884 IVars.push_back(IVD); 06885 } 06886 06887 Write__ivar_list_t_initializer(*this, Context, Result, IVars, 06888 "_OBJC_$_INSTANCE_VARIABLES_", 06889 CDecl); 06890 06891 // Build _objc_method_list for class's instance methods if needed 06892 SmallVector<ObjCMethodDecl *, 32> 06893 InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 06894 06895 // If any of our property implementations have associated getters or 06896 // setters, produce metadata for them as well. 06897 for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 06898 PropEnd = IDecl->propimpl_end(); 06899 Prop != PropEnd; ++Prop) { 06900 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 06901 continue; 06902 if (!Prop->getPropertyIvarDecl()) 06903 continue; 06904 ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 06905 if (!PD) 06906 continue; 06907 if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 06908 if (mustSynthesizeSetterGetterMethod(IDecl, PD, true /*getter*/)) 06909 InstanceMethods.push_back(Getter); 06910 if (PD->isReadOnly()) 06911 continue; 06912 if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 06913 if (mustSynthesizeSetterGetterMethod(IDecl, PD, false /*setter*/)) 06914 InstanceMethods.push_back(Setter); 06915 } 06916 06917 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 06918 "_OBJC_$_INSTANCE_METHODS_", 06919 IDecl->getNameAsString(), true); 06920 06921 SmallVector<ObjCMethodDecl *, 32> 06922 ClassMethods(IDecl->classmeth_begin(), IDecl->classmeth_end()); 06923 06924 Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 06925 "_OBJC_$_CLASS_METHODS_", 06926 IDecl->getNameAsString(), true); 06927 06928 // Protocols referenced in class declaration? 06929 // Protocol's super protocol list 06930 std::vector<ObjCProtocolDecl *> RefedProtocols; 06931 const ObjCList<ObjCProtocolDecl> &Protocols = CDecl->getReferencedProtocols(); 06932 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), 06933 E = Protocols.end(); 06934 I != E; ++I) { 06935 RefedProtocols.push_back(*I); 06936 // Must write out all protocol definitions in current qualifier list, 06937 // and in their nested qualifiers before writing out current definition. 06938 RewriteObjCProtocolMetaData(*I, Result); 06939 } 06940 06941 Write_protocol_list_initializer(Context, Result, 06942 RefedProtocols, 06943 "_OBJC_CLASS_PROTOCOLS_$_", 06944 IDecl->getNameAsString()); 06945 06946 // Protocol's property metadata. 06947 std::vector<ObjCPropertyDecl *> ClassProperties; 06948 for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), 06949 E = CDecl->prop_end(); I != E; ++I) 06950 ClassProperties.push_back(&*I); 06951 06952 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties, 06953 /* Container */IDecl, 06954 "_OBJC_$_PROP_LIST_", 06955 CDecl->getNameAsString()); 06956 06957 06958 // Data for initializing _class_ro_t metaclass meta-data 06959 uint32_t flags = CLS_META; 06960 std::string InstanceSize; 06961 std::string InstanceStart; 06962 06963 06964 bool classIsHidden = CDecl->getVisibility() == HiddenVisibility; 06965 if (classIsHidden) 06966 flags |= OBJC2_CLS_HIDDEN; 06967 06968 if (!CDecl->getSuperClass()) 06969 // class is root 06970 flags |= CLS_ROOT; 06971 InstanceSize = "sizeof(struct _class_t)"; 06972 InstanceStart = InstanceSize; 06973 Write__class_ro_t_initializer(Context, Result, flags, 06974 InstanceStart, InstanceSize, 06975 ClassMethods, 06976 0, 06977 0, 06978 0, 06979 "_OBJC_METACLASS_RO_$_", 06980 CDecl->getNameAsString()); 06981 06982 06983 // Data for initializing _class_ro_t meta-data 06984 flags = CLS; 06985 if (classIsHidden) 06986 flags |= OBJC2_CLS_HIDDEN; 06987 06988 if (hasObjCExceptionAttribute(*Context, CDecl)) 06989 flags |= CLS_EXCEPTION; 06990 06991 if (!CDecl->getSuperClass()) 06992 // class is root 06993 flags |= CLS_ROOT; 06994 06995 InstanceSize.clear(); 06996 InstanceStart.clear(); 06997 if (!ObjCSynthesizedStructs.count(CDecl)) { 06998 InstanceSize = "0"; 06999 InstanceStart = "0"; 07000 } 07001 else { 07002 InstanceSize = "sizeof(struct "; 07003 InstanceSize += CDecl->getNameAsString(); 07004 InstanceSize += "_IMPL)"; 07005 07006 ObjCIvarDecl *IVD = CDecl->all_declared_ivar_begin(); 07007 if (IVD) { 07008 RewriteIvarOffsetComputation(IVD, InstanceStart); 07009 } 07010 else 07011 InstanceStart = InstanceSize; 07012 } 07013 Write__class_ro_t_initializer(Context, Result, flags, 07014 InstanceStart, InstanceSize, 07015 InstanceMethods, 07016 RefedProtocols, 07017 IVars, 07018 ClassProperties, 07019 "_OBJC_CLASS_RO_$_", 07020 CDecl->getNameAsString()); 07021 07022 Write_class_t(Context, Result, 07023 "OBJC_METACLASS_$_", 07024 CDecl, /*metaclass*/true); 07025 07026 Write_class_t(Context, Result, 07027 "OBJC_CLASS_$_", 07028 CDecl, /*metaclass*/false); 07029 07030 if (ImplementationIsNonLazy(IDecl)) 07031 DefinedNonLazyClasses.push_back(CDecl); 07032 07033 } 07034 07035 void RewriteModernObjC::RewriteClassSetupInitHook(std::string &Result) { 07036 int ClsDefCount = ClassImplementation.size(); 07037 if (!ClsDefCount) 07038 return; 07039 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n"; 07040 Result += "__declspec(allocate(\".objc_inithooks$B\")) "; 07041 Result += "static void *OBJC_CLASS_SETUP[] = {\n"; 07042 for (int i = 0; i < ClsDefCount; i++) { 07043 ObjCImplementationDecl *IDecl = ClassImplementation[i]; 07044 ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); 07045 Result += "\t(void *)&OBJC_CLASS_SETUP_$_"; 07046 Result += CDecl->getName(); Result += ",\n"; 07047 } 07048 Result += "};\n"; 07049 } 07050 07051 void RewriteModernObjC::RewriteMetaDataIntoBuffer(std::string &Result) { 07052 int ClsDefCount = ClassImplementation.size(); 07053 int CatDefCount = CategoryImplementation.size(); 07054 07055 // For each implemented class, write out all its meta data. 07056 for (int i = 0; i < ClsDefCount; i++) 07057 RewriteObjCClassMetaData(ClassImplementation[i], Result); 07058 07059 RewriteClassSetupInitHook(Result); 07060 07061 // For each implemented category, write out all its meta data. 07062 for (int i = 0; i < CatDefCount; i++) 07063 RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); 07064 07065 RewriteCategorySetupInitHook(Result); 07066 07067 if (ClsDefCount > 0) { 07068 if (LangOpts.MicrosoftExt) 07069 Result += "__declspec(allocate(\".objc_classlist$B\")) "; 07070 Result += "static struct _class_t *L_OBJC_LABEL_CLASS_$ ["; 07071 Result += llvm::utostr(ClsDefCount); Result += "]"; 07072 Result += 07073 " __attribute__((used, section (\"__DATA, __objc_classlist," 07074 "regular,no_dead_strip\")))= {\n"; 07075 for (int i = 0; i < ClsDefCount; i++) { 07076 Result += "\t&OBJC_CLASS_$_"; 07077 Result += ClassImplementation[i]->getNameAsString(); 07078 Result += ",\n"; 07079 } 07080 Result += "};\n"; 07081 07082 if (!DefinedNonLazyClasses.empty()) { 07083 if (LangOpts.MicrosoftExt) 07084 Result += "__declspec(allocate(\".objc_nlclslist$B\")) \n"; 07085 Result += "static struct _class_t *_OBJC_LABEL_NONLAZY_CLASS_$[] = {\n\t"; 07086 for (unsigned i = 0, e = DefinedNonLazyClasses.size(); i < e; i++) { 07087 Result += "\t&OBJC_CLASS_$_"; Result += DefinedNonLazyClasses[i]->getNameAsString(); 07088 Result += ",\n"; 07089 } 07090 Result += "};\n"; 07091 } 07092 } 07093 07094 if (CatDefCount > 0) { 07095 if (LangOpts.MicrosoftExt) 07096 Result += "__declspec(allocate(\".objc_catlist$B\")) "; 07097 Result += "static struct _category_t *L_OBJC_LABEL_CATEGORY_$ ["; 07098 Result += llvm::utostr(CatDefCount); Result += "]"; 07099 Result += 07100 " __attribute__((used, section (\"__DATA, __objc_catlist," 07101 "regular,no_dead_strip\")))= {\n"; 07102 for (int i = 0; i < CatDefCount; i++) { 07103 Result += "\t&_OBJC_$_CATEGORY_"; 07104 Result += 07105 CategoryImplementation[i]->getClassInterface()->getNameAsString(); 07106 Result += "_$_"; 07107 Result += CategoryImplementation[i]->getNameAsString(); 07108 Result += ",\n"; 07109 } 07110 Result += "};\n"; 07111 } 07112 07113 if (!DefinedNonLazyCategories.empty()) { 07114 if (LangOpts.MicrosoftExt) 07115 Result += "__declspec(allocate(\".objc_nlcatlist$B\")) \n"; 07116 Result += "static struct _category_t *_OBJC_LABEL_NONLAZY_CATEGORY_$[] = {\n\t"; 07117 for (unsigned i = 0, e = DefinedNonLazyCategories.size(); i < e; i++) { 07118 Result += "\t&_OBJC_$_CATEGORY_"; 07119 Result += 07120 DefinedNonLazyCategories[i]->getClassInterface()->getNameAsString(); 07121 Result += "_$_"; 07122 Result += DefinedNonLazyCategories[i]->getNameAsString(); 07123 Result += ",\n"; 07124 } 07125 Result += "};\n"; 07126 } 07127 } 07128 07129 void RewriteModernObjC::WriteImageInfo(std::string &Result) { 07130 if (LangOpts.MicrosoftExt) 07131 Result += "__declspec(allocate(\".objc_imageinfo$B\")) \n"; 07132 07133 Result += "static struct IMAGE_INFO { unsigned version; unsigned flag; } "; 07134 // version 0, ObjCABI is 2 07135 Result += "_OBJC_IMAGE_INFO = { 0, 2 };\n"; 07136 } 07137 07138 /// RewriteObjCCategoryImplDecl - Rewrite metadata for each category 07139 /// implementation. 07140 void RewriteModernObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, 07141 std::string &Result) { 07142 WriteModernMetadataDeclarations(Context, Result); 07143 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 07144 // Find category declaration for this implementation. 07145 ObjCCategoryDecl *CDecl=0; 07146 for (CDecl = ClassDecl->getCategoryList(); CDecl; 07147 CDecl = CDecl->getNextClassCategory()) 07148 if (CDecl->getIdentifier() == IDecl->getIdentifier()) 07149 break; 07150 07151 std::string FullCategoryName = ClassDecl->getNameAsString(); 07152 FullCategoryName += "_$_"; 07153 FullCategoryName += CDecl->getNameAsString(); 07154 07155 // Build _objc_method_list for class's instance methods if needed 07156 SmallVector<ObjCMethodDecl *, 32> 07157 InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); 07158 07159 // If any of our property implementations have associated getters or 07160 // setters, produce metadata for them as well. 07161 for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), 07162 PropEnd = IDecl->propimpl_end(); 07163 Prop != PropEnd; ++Prop) { 07164 if (Prop->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 07165 continue; 07166 if (!Prop->getPropertyIvarDecl()) 07167 continue; 07168 ObjCPropertyDecl *PD = Prop->getPropertyDecl(); 07169 if (!PD) 07170 continue; 07171 if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) 07172 InstanceMethods.push_back(Getter); 07173 if (PD->isReadOnly()) 07174 continue; 07175 if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) 07176 InstanceMethods.push_back(Setter); 07177 } 07178 07179 Write_method_list_t_initializer(*this, Context, Result, InstanceMethods, 07180 "_OBJC_$_CATEGORY_INSTANCE_METHODS_", 07181 FullCategoryName, true); 07182 07183 SmallVector<ObjCMethodDecl *, 32> 07184 ClassMethods(IDecl->classmeth_begin(), IDecl->classmeth_end()); 07185 07186 Write_method_list_t_initializer(*this, Context, Result, ClassMethods, 07187 "_OBJC_$_CATEGORY_CLASS_METHODS_", 07188 FullCategoryName, true); 07189 07190 // Protocols referenced in class declaration? 07191 // Protocol's super protocol list 07192 std::vector<ObjCProtocolDecl *> RefedProtocols; 07193 for (ObjCInterfaceDecl::protocol_iterator I = CDecl->protocol_begin(), 07194 E = CDecl->protocol_end(); 07195 07196 I != E; ++I) { 07197 RefedProtocols.push_back(*I); 07198 // Must write out all protocol definitions in current qualifier list, 07199 // and in their nested qualifiers before writing out current definition. 07200 RewriteObjCProtocolMetaData(*I, Result); 07201 } 07202 07203 Write_protocol_list_initializer(Context, Result, 07204 RefedProtocols, 07205 "_OBJC_CATEGORY_PROTOCOLS_$_", 07206 FullCategoryName); 07207 07208 // Protocol's property metadata. 07209 std::vector<ObjCPropertyDecl *> ClassProperties; 07210 for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), 07211 E = CDecl->prop_end(); I != E; ++I) 07212 ClassProperties.push_back(&*I); 07213 07214 Write_prop_list_t_initializer(*this, Context, Result, ClassProperties, 07215 /* Container */IDecl, 07216 "_OBJC_$_PROP_LIST_", 07217 FullCategoryName); 07218 07219 Write_category_t(*this, Context, Result, 07220 CDecl, 07221 ClassDecl, 07222 InstanceMethods, 07223 ClassMethods, 07224 RefedProtocols, 07225 ClassProperties); 07226 07227 // Determine if this category is also "non-lazy". 07228 if (ImplementationIsNonLazy(IDecl)) 07229 DefinedNonLazyCategories.push_back(CDecl); 07230 07231 } 07232 07233 void RewriteModernObjC::RewriteCategorySetupInitHook(std::string &Result) { 07234 int CatDefCount = CategoryImplementation.size(); 07235 if (!CatDefCount) 07236 return; 07237 Result += "#pragma section(\".objc_inithooks$B\", long, read, write)\n"; 07238 Result += "__declspec(allocate(\".objc_inithooks$B\")) "; 07239 Result += "static void *OBJC_CATEGORY_SETUP[] = {\n"; 07240 for (int i = 0; i < CatDefCount; i++) { 07241 ObjCCategoryImplDecl *IDecl = CategoryImplementation[i]; 07242 ObjCCategoryDecl *CatDecl= IDecl->getCategoryDecl(); 07243 ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); 07244 Result += "\t(void *)&OBJC_CATEGORY_SETUP_$_"; 07245 Result += ClassDecl->getName(); 07246 Result += "_$_"; 07247 Result += CatDecl->getName(); 07248 Result += ",\n"; 07249 } 07250 Result += "};\n"; 07251 } 07252 07253 // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or 07254 /// class methods. 07255 template<typename MethodIterator> 07256 void RewriteModernObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, 07257 MethodIterator MethodEnd, 07258 bool IsInstanceMethod, 07259 StringRef prefix, 07260 StringRef ClassName, 07261 std::string &Result) { 07262 if (MethodBegin == MethodEnd) return; 07263 07264 if (!objc_impl_method) { 07265 /* struct _objc_method { 07266 SEL _cmd; 07267 char *method_types; 07268 void *_imp; 07269 } 07270 */ 07271 Result += "\nstruct _objc_method {\n"; 07272 Result += "\tSEL _cmd;\n"; 07273 Result += "\tchar *method_types;\n"; 07274 Result += "\tvoid *_imp;\n"; 07275 Result += "};\n"; 07276 07277 objc_impl_method = true; 07278 } 07279 07280 // Build _objc_method_list for class's methods if needed 07281 07282 /* struct { 07283 struct _objc_method_list *next_method; 07284 int method_count; 07285 struct _objc_method method_list[]; 07286 } 07287 */ 07288 unsigned NumMethods = std::distance(MethodBegin, MethodEnd); 07289 Result += "\n"; 07290 if (LangOpts.MicrosoftExt) { 07291 if (IsInstanceMethod) 07292 Result += "__declspec(allocate(\".inst_meth$B\")) "; 07293 else 07294 Result += "__declspec(allocate(\".cls_meth$B\")) "; 07295 } 07296 Result += "static struct {\n"; 07297 Result += "\tstruct _objc_method_list *next_method;\n"; 07298 Result += "\tint method_count;\n"; 07299 Result += "\tstruct _objc_method method_list["; 07300 Result += utostr(NumMethods); 07301 Result += "];\n} _OBJC_"; 07302 Result += prefix; 07303 Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; 07304 Result += "_METHODS_"; 07305 Result += ClassName; 07306 Result += " __attribute__ ((used, section (\"__OBJC, __"; 07307 Result += IsInstanceMethod ? "inst" : "cls"; 07308 Result += "_meth\")))= "; 07309 Result += "{\n\t0, " + utostr(NumMethods) + "\n"; 07310 07311 Result += "\t,{{(SEL)\""; 07312 Result += (*MethodBegin)->getSelector().getAsString().c_str(); 07313 std::string MethodTypeString; 07314 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 07315 Result += "\", \""; 07316 Result += MethodTypeString; 07317 Result += "\", (void *)"; 07318 Result += MethodInternalNames[*MethodBegin]; 07319 Result += "}\n"; 07320 for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { 07321 Result += "\t ,{(SEL)\""; 07322 Result += (*MethodBegin)->getSelector().getAsString().c_str(); 07323 std::string MethodTypeString; 07324 Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); 07325 Result += "\", \""; 07326 Result += MethodTypeString; 07327 Result += "\", (void *)"; 07328 Result += MethodInternalNames[*MethodBegin]; 07329 Result += "}\n"; 07330 } 07331 Result += "\t }\n};\n"; 07332 } 07333 07334 Stmt *RewriteModernObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { 07335 SourceRange OldRange = IV->getSourceRange(); 07336 Expr *BaseExpr = IV->getBase(); 07337 07338 // Rewrite the base, but without actually doing replaces. 07339 { 07340 DisableReplaceStmtScope S(*this); 07341 BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr)); 07342 IV->setBase(BaseExpr); 07343 } 07344 07345 ObjCIvarDecl *D = IV->getDecl(); 07346 07347 Expr *Replacement = IV; 07348 07349 if (BaseExpr->getType()->isObjCObjectPointerType()) { 07350 const ObjCInterfaceType *iFaceDecl = 07351 dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); 07352 assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); 07353 // lookup which class implements the instance variable. 07354 ObjCInterfaceDecl *clsDeclared = 0; 07355 iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), 07356 clsDeclared); 07357 assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); 07358 07359 // Build name of symbol holding ivar offset. 07360 std::string IvarOffsetName; 07361 WriteInternalIvarName(clsDeclared, D, IvarOffsetName); 07362 07363 ReferencedIvars[clsDeclared].insert(D); 07364 07365 // cast offset to "char *". 07366 CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, 07367 Context->getPointerType(Context->CharTy), 07368 CK_BitCast, 07369 BaseExpr); 07370 VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), 07371 SourceLocation(), &Context->Idents.get(IvarOffsetName), 07372 Context->UnsignedLongTy, 0, SC_Extern, SC_None); 07373 DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, 07374 Context->UnsignedLongTy, VK_LValue, 07375 SourceLocation()); 07376 BinaryOperator *addExpr = 07377 new (Context) BinaryOperator(castExpr, DRE, BO_Add, 07378 Context->getPointerType(Context->CharTy), 07379 VK_RValue, OK_Ordinary, SourceLocation()); 07380 // Don't forget the parens to enforce the proper binding. 07381 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), 07382 SourceLocation(), 07383 addExpr); 07384 QualType IvarT = D->getType(); 07385 07386 if (!isa<TypedefType>(IvarT) && IvarT->isRecordType()) { 07387 RecordDecl *RD = IvarT->getAs<RecordType>()->getDecl(); 07388 RD = RD->getDefinition(); 07389 if (RD && !RD->getDeclName().getAsIdentifierInfo()) { 07390 // decltype(((Foo_IMPL*)0)->bar) * 07391 ObjCContainerDecl *CDecl = 07392 dyn_cast<ObjCContainerDecl>(D->getDeclContext()); 07393 // ivar in class extensions requires special treatment. 07394 if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) 07395 CDecl = CatDecl->getClassInterface(); 07396 std::string RecName = CDecl->getName(); 07397 RecName += "_IMPL"; 07398 RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, 07399 SourceLocation(), SourceLocation(), 07400 &Context->Idents.get(RecName.c_str())); 07401 QualType PtrStructIMPL = Context->getPointerType(Context->getTagDeclType(RD)); 07402 unsigned UnsignedIntSize = 07403 static_cast<unsigned>(Context->getTypeSize(Context->UnsignedIntTy)); 07404 Expr *Zero = IntegerLiteral::Create(*Context, 07405 llvm::APInt(UnsignedIntSize, 0), 07406 Context->UnsignedIntTy, SourceLocation()); 07407 Zero = NoTypeInfoCStyleCastExpr(Context, PtrStructIMPL, CK_BitCast, Zero); 07408 ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), 07409 Zero); 07410 FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), 07411 SourceLocation(), 07412 &Context->Idents.get(D->getNameAsString()), 07413 IvarT, 0, 07414 /*BitWidth=*/0, /*Mutable=*/true, 07415 /*HasInit=*/false); 07416 MemberExpr *ME = new (Context) MemberExpr(PE, true, FD, SourceLocation(), 07417 FD->getType(), VK_LValue, 07418 OK_Ordinary); 07419 IvarT = Context->getDecltypeType(ME, ME->getType()); 07420 } 07421 } 07422 convertObjCTypeToCStyleType(IvarT); 07423 QualType castT = Context->getPointerType(IvarT); 07424 07425 castExpr = NoTypeInfoCStyleCastExpr(Context, 07426 castT, 07427 CK_BitCast, 07428 PE); 07429 07430 07431 Expr *Exp = new (Context) UnaryOperator(castExpr, UO_Deref, IvarT, 07432 VK_LValue, OK_Ordinary, 07433 SourceLocation()); 07434 PE = new (Context) ParenExpr(OldRange.getBegin(), 07435 OldRange.getEnd(), 07436 Exp); 07437 07438 Replacement = PE; 07439 } 07440 07441 ReplaceStmtWithRange(IV, Replacement, OldRange); 07442 return Replacement; 07443 }