diff options
Diffstat (limited to 'lib/Rewrite/RewriteObjC.cpp')
-rw-r--r-- | lib/Rewrite/RewriteObjC.cpp | 3197 |
1 files changed, 1577 insertions, 1620 deletions
diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index 6a392ea357f1..9c0737f659a6 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/lib/Rewrite/RewriteObjC.cpp @@ -32,6 +32,8 @@ using llvm::utostr; namespace { class RewriteObjC : public ASTConsumer { + protected: + enum { BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), block, ... */ @@ -53,35 +55,39 @@ namespace { BLOCK_IS_GLOBAL = (1 << 28), BLOCK_HAS_DESCRIPTOR = (1 << 29) }; + static const int OBJC_ABI_VERSION = 7; Rewriter Rewrite; DiagnosticsEngine &Diags; const LangOptions &LangOpts; - unsigned RewriteFailedDiag; - unsigned TryFinallyContainsReturnDiag; - ASTContext *Context; SourceManager *SM; TranslationUnitDecl *TUDecl; FileID MainFileID; const char *MainFileStart, *MainFileEnd; - SourceLocation LastIncLoc; - - SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; - SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; - llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; - llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; - llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls; - llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; - SmallVector<Stmt *, 32> Stmts; - SmallVector<int, 8> ObjCBcLabelNo; - // Remember all the @protocol(<expr>) expressions. - llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; - - llvm::DenseSet<uint64_t> CopyDestroyCache; + Stmt *CurrentBody; + ParentMap *PropParentMap; // created lazily. + std::string InFileName; + raw_ostream* OutFile; + std::string Preamble; + TypeDecl *ProtocolTypeDecl; + VarDecl *GlobalVarDecl; + unsigned RewriteFailedDiag; + // ObjC string constant support. unsigned NumObjCStringLiterals; + VarDecl *ConstantStringClassReference; + RecordDecl *NSStringRecord; + // ObjC foreach break/continue generation support. + int BcLabelCount; + + unsigned TryFinallyContainsReturnDiag; + // Needed for super. + ObjCMethodDecl *CurMethodDef; + RecordDecl *SuperStructDecl; + RecordDecl *ConstantStringDecl; + FunctionDecl *MsgSendFunctionDecl; FunctionDecl *MsgSendSuperFunctionDecl; FunctionDecl *MsgSendStretFunctionDecl; @@ -93,39 +99,29 @@ namespace { FunctionDecl *SelGetUidFunctionDecl; FunctionDecl *CFStringFunctionDecl; FunctionDecl *SuperContructorFunctionDecl; + FunctionDecl *CurFunctionDef; + FunctionDecl *CurFunctionDeclToDeclareForBlock; - // ObjC string constant support. - VarDecl *ConstantStringClassReference; - RecordDecl *NSStringRecord; - - // ObjC foreach break/continue generation support. - int BcLabelCount; - - // Needed for super. - ObjCMethodDecl *CurMethodDef; - RecordDecl *SuperStructDecl; - RecordDecl *ConstantStringDecl; - - TypeDecl *ProtocolTypeDecl; - QualType getProtocolType(); - - // Needed for header files being rewritten - bool IsHeader; - - std::string InFileName; - raw_ostream* OutFile; - - bool SilenceRewriteMacroWarning; - bool objc_impl_method; - - std::string Preamble; + /* Misc. containers needed for meta-data rewrite. */ + SmallVector<ObjCImplementationDecl *, 8> ClassImplementation; + SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation; + llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs; + llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols; + llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls; + llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; + SmallVector<Stmt *, 32> Stmts; + SmallVector<int, 8> ObjCBcLabelNo; + // Remember all the @protocol(<expr>) expressions. + llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; + + llvm::DenseSet<uint64_t> CopyDestroyCache; // Block expressions. SmallVector<BlockExpr *, 32> Blocks; SmallVector<int, 32> InnerDeclRefsCount; - SmallVector<BlockDeclRefExpr *, 32> InnerDeclRefs; + SmallVector<DeclRefExpr *, 32> InnerDeclRefs; - SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs; + SmallVector<DeclRefExpr *, 32> BlockDeclRefs; // Block related declarations. SmallVector<ValueDecl *, 8> BlockByCopyDecls; @@ -138,36 +134,54 @@ namespace { llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs; - // This maps a property to it's assignment statement. - llvm::DenseMap<Expr *, BinaryOperator *> PropSetters; - // This maps a property to it's synthesied message expression. - // This allows us to rewrite chained getters (e.g. o.a.b.c). - llvm::DenseMap<Expr *, Stmt *> PropGetters; - // This maps an original source AST to it's rewritten form. This allows // us to avoid rewriting the same node twice (which is very uncommon). // This is needed to support some of the exotic property rewriting. llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes; - FunctionDecl *CurFunctionDef; - FunctionDecl *CurFunctionDeclToDeclareForBlock; - VarDecl *GlobalVarDecl; - + // Needed for header files being rewritten + bool IsHeader; + bool SilenceRewriteMacroWarning; + bool objc_impl_method; + bool DisableReplaceStmt; + class DisableReplaceStmtScope { + RewriteObjC &R; + bool SavedValue; + + public: + DisableReplaceStmtScope(RewriteObjC &R) + : R(R), SavedValue(R.DisableReplaceStmt) { + R.DisableReplaceStmt = true; + } + ~DisableReplaceStmtScope() { + R.DisableReplaceStmt = SavedValue; + } + }; + void InitializeCommon(ASTContext &context); - static const int OBJC_ABI_VERSION = 7; public: - virtual void Initialize(ASTContext &context); // Top Level Driver code. - virtual void HandleTopLevelDecl(DeclGroupRef D) { + virtual bool HandleTopLevelDecl(DeclGroupRef D) { for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { - if (isa<ObjCClassDecl>((*I))) { - RewriteForwardClassDecl(D); - break; + if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*I)) { + if (!Class->isThisDeclarationADefinition()) { + RewriteForwardClassDecl(D); + break; + } + } + + if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*I)) { + if (!Proto->isThisDeclarationADefinition()) { + RewriteForwardProtocolDecl(D); + break; + } } + HandleTopLevelSingleDecl(*I); } + return true; } void HandleTopLevelSingleDecl(Decl *D); void HandleDeclInMainFile(Decl *D); @@ -186,7 +200,7 @@ namespace { return; // We can't rewrite the same node twice. if (DisableReplaceStmt) - return; // Used when rewriting the assignment of a property setter. + return; // If replacement succeeded or warning disabled return with no warning. if (!Rewrite.ReplaceStmt(Old, New)) { @@ -200,6 +214,9 @@ namespace { } void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) { + if (DisableReplaceStmt) + return; + // Measure the old text. int Size = Rewrite.getRangeSize(SrcRange); if (Size == -1) { @@ -245,12 +262,13 @@ namespace { } // Syntactic Rewriting. + void RewriteRecordBody(RecordDecl *RD); void RewriteInclude(); void RewriteForwardClassDecl(DeclGroupRef D); void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG); - void RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, + void RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, const std::string &typedefString); - + void RewriteImplementations(); void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, ObjCImplementationDecl *IMD, ObjCCategoryImplDecl *CID); @@ -264,7 +282,8 @@ namespace { ValueDecl *VD, bool def=false); void RewriteCategoryDecl(ObjCCategoryDecl *Dcl); void RewriteProtocolDecl(ObjCProtocolDecl *Dcl); - void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl); + void RewriteForwardProtocolDecl(DeclGroupRef D); + void RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG); void RewriteMethodDeclaration(ObjCMethodDecl *Method); void RewriteProperty(ObjCPropertyDecl *prop); void RewriteFunctionDecl(FunctionDecl *FD); @@ -274,32 +293,16 @@ namespace { void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); void RewriteTypeOfDecl(VarDecl *VD); void RewriteObjCQualifiedInterfaceTypes(Expr *E); - bool needToScanForQualifiers(QualType T); - QualType getSuperStructType(); - QualType getConstantStringStructType(); - QualType convertFunctionTypeOfBlocks(const FunctionType *FT); - bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); - + // Expression Rewriting. Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S); - void CollectPropertySetters(Stmt *S); - - Stmt *CurrentBody; - ParentMap *PropParentMap; // created lazily. - Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); - Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart, - bool &replaced); - Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced); - Stmt *RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr); - Stmt *RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt, - SourceRange SrcRange); + Stmt *RewritePropertyOrImplicitGetter(PseudoObjectExpr *Pseudo); + Stmt *RewritePropertyOrImplicitSetter(PseudoObjectExpr *Pseudo); Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp); Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp); Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp); Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp); - void WarnAboutReturnGotoStmts(Stmt *S); - void HasReturnStmts(Stmt *S, bool &hasReturns); void RewriteTryReturnStmts(Stmt *S); void RewriteSyncReturnStmts(Stmt *S, std::string buf); Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S); @@ -307,18 +310,57 @@ namespace { Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S); Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, SourceLocation OrigEnd); - bool IsDeclStmtInForeachHeader(DeclStmt *DS); + Stmt *RewriteBreakStmt(BreakStmt *S); + Stmt *RewriteContinueStmt(ContinueStmt *S); + void RewriteCastExpr(CStyleCastExpr *CE); + + // Block rewriting. + void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); + + // Block specific rewrite rules. + void RewriteBlockPointerDecl(NamedDecl *VD); + void RewriteByRefVar(VarDecl *VD); + Stmt *RewriteBlockDeclRefExpr(DeclRefExpr *VD); + Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); + void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); + + void RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, + std::string &Result); + + virtual void Initialize(ASTContext &context) = 0; + + // Metadata Rewriting. + virtual void RewriteMetaDataIntoBuffer(std::string &Result) = 0; + virtual void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, + StringRef prefix, + StringRef ClassName, + std::string &Result) = 0; + virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, + std::string &Result) = 0; + virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, + StringRef prefix, + StringRef ClassName, + std::string &Result) = 0; + virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, + std::string &Result) = 0; + + // Rewriting ivar access + virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) = 0; + virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, + std::string &Result) = 0; + + // Misc. AST transformation routines. Somtimes they end up calling + // rewriting routines on the new ASTs. CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD, - Expr **args, unsigned nargs, - SourceLocation StartLoc=SourceLocation(), - SourceLocation EndLoc=SourceLocation()); + Expr **args, unsigned nargs, + SourceLocation StartLoc=SourceLocation(), + SourceLocation EndLoc=SourceLocation()); + Stmt *SynthMessageExpr(ObjCMessageExpr *Exp, SourceLocation StartLoc=SourceLocation(), SourceLocation EndLoc=SourceLocation()); - Stmt *RewriteBreakStmt(BreakStmt *S); - Stmt *RewriteContinueStmt(ContinueStmt *S); + void SynthCountByEnumWithState(std::string &buf); - void SynthMsgSendFunctionDecl(); void SynthMsgSendSuperFunctionDecl(); void SynthMsgSendStretFunctionDecl(); @@ -329,52 +371,8 @@ namespace { void SynthGetSuperClassFunctionDecl(); void SynthSelGetUidFunctionDecl(); void SynthSuperContructorFunctionDecl(); - - // Metadata emission. - void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, - std::string &Result); - - void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, - std::string &Result); - - template<typename MethodIterator> - void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, - MethodIterator MethodEnd, - bool IsInstanceMethod, - StringRef prefix, - StringRef ClassName, - std::string &Result); - - void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, - StringRef prefix, - StringRef ClassName, - std::string &Result); - void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, - StringRef prefix, - StringRef ClassName, - std::string &Result); - void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, - std::string &Result); - void SynthesizeIvarOffsetComputation(ObjCIvarDecl *ivar, - std::string &Result); - void RewriteImplementations(); - void SynthesizeMetaDataIntoBuffer(std::string &Result); - - // Block rewriting. - void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D); - void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); - - void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); - void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); - - // Block specific rewrite rules. - void RewriteBlockPointerDecl(NamedDecl *VD); - void RewriteByRefVar(VarDecl *VD); + std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag); - Stmt *RewriteBlockDeclRefExpr(Expr *VD); - Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE); - void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); - std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, StringRef funcName, std::string Tag); std::string SynthesizeBlockFunc(BlockExpr *CE, int i, @@ -388,12 +386,23 @@ namespace { Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp); void SynthesizeBlockLiterals(SourceLocation FunLocStart, StringRef FunName); - void RewriteRecordBody(RecordDecl *RD); + FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); + Stmt *SynthBlockInitExpr(BlockExpr *Exp, + const SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs); + // Misc. helper routines. + QualType getProtocolType(); + void WarnAboutReturnGotoStmts(Stmt *S); + void HasReturnStmts(Stmt *S, bool &hasReturns); + void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND); + void InsertBlockLiteralsWithinFunction(FunctionDecl *FD); + void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD); + + bool IsDeclStmtInForeachHeader(DeclStmt *DS); void CollectBlockDeclRefInfo(BlockExpr *Exp); void GetBlockDeclRefExprs(Stmt *S); void GetInnerBlockDeclRefExprs(Stmt *S, - SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs, + SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs, llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts); // We avoid calling Type::isBlockPointerType(), since it operates on the @@ -414,6 +423,12 @@ namespace { return false; } + bool needToScanForQualifiers(QualType T); + QualType getSuperStructType(); + QualType getConstantStringStructType(); + QualType convertFunctionTypeOfBlocks(const FunctionType *FT); + bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf); + void convertToUnqualifiedObjCType(QualType &T) { if (T->isObjCQualifiedIdType()) T = Context->getObjCIdType(); @@ -452,12 +467,7 @@ namespace { bool PointerTypeTakesAnyObjCQualifiedType(QualType QT); void GetExtentOfArgList(const char *Name, const char *&LParen, const char *&RParen); - void RewriteCastExpr(CStyleCastExpr *CE); - - FunctionDecl *SynthBlockInitFunctionDecl(StringRef name); - Stmt *SynthBlockInitExpr(BlockExpr *Exp, - const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs); - + void QuoteDoublequotes(std::string &From, std::string &To) { for (unsigned i = 0; i < From.length(); i++) { if (From[i] == '"') @@ -477,15 +487,54 @@ namespace { fpi.Variadic = variadic; return Context->getFunctionType(result, args, numArgs, fpi); } - }; - // Helper function: create a CStyleCastExpr with trivial type source info. - CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, - CastKind Kind, Expr *E) { - TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); - return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo, - SourceLocation(), SourceLocation()); - } + // Helper function: create a CStyleCastExpr with trivial type source info. + CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty, + CastKind Kind, Expr *E) { + TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation()); + return CStyleCastExpr::Create(*Ctx, Ty, VK_RValue, Kind, E, 0, TInfo, + SourceLocation(), SourceLocation()); + } + }; + + class RewriteObjCFragileABI : public RewriteObjC { + public: + + RewriteObjCFragileABI(std::string inFile, raw_ostream *OS, + DiagnosticsEngine &D, const LangOptions &LOpts, + bool silenceMacroWarn) : RewriteObjC(inFile, OS, + D, LOpts, + silenceMacroWarn) {} + + ~RewriteObjCFragileABI() {} + virtual void Initialize(ASTContext &context); + + // Rewriting metadata + template<typename MethodIterator> + void RewriteObjCMethodsMetaData(MethodIterator MethodBegin, + MethodIterator MethodEnd, + bool IsInstanceMethod, + StringRef prefix, + StringRef ClassName, + std::string &Result); + virtual void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, + StringRef prefix, + StringRef ClassName, + std::string &Result); + virtual void RewriteObjCProtocolListMetaData( + const ObjCList<ObjCProtocolDecl> &Prots, + StringRef prefix, StringRef ClassName, std::string &Result); + virtual void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, + std::string &Result); + virtual void RewriteMetaDataIntoBuffer(std::string &Result); + virtual void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl, + std::string &Result); + + // Rewriting ivar + virtual void RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, + std::string &Result); + virtual Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV); + }; } void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType, @@ -541,10 +590,10 @@ ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile, DiagnosticsEngine &Diags, const LangOptions &LOpts, bool SilenceRewriteMacroWarning) { - return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); + return new RewriteObjCFragileABI(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning); } -void RewriteObjC::Initialize(ASTContext &context) { +void RewriteObjC::InitializeCommon(ASTContext &context) { Context = &context; SM = &Context->getSourceManager(); TUDecl = Context->getTranslationUnitDecl(); @@ -581,121 +630,9 @@ void RewriteObjC::Initialize(ASTContext &context) { MainFileStart = MainBuf->getBufferStart(); MainFileEnd = MainBuf->getBufferEnd(); - Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions()); - - // declaring objc_selector outside the parameter list removes a silly - // scope related warning... - if (IsHeader) - Preamble = "#pragma once\n"; - Preamble += "struct objc_selector; struct objc_class;\n"; - Preamble += "struct __rw_objc_super { struct objc_object *object; "; - Preamble += "struct objc_object *superClass; "; - if (LangOpts.MicrosoftExt) { - // Add a constructor for creating temporary objects. - Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) " - ": "; - Preamble += "object(o), superClass(s) {} "; - } - Preamble += "};\n"; - Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; - Preamble += "typedef struct objc_object Protocol;\n"; - Preamble += "#define _REWRITER_typedef_Protocol\n"; - Preamble += "#endif\n"; - if (LangOpts.MicrosoftExt) { - Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; - Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; - } else - Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; - Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend"; - Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; - Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper"; - Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; - Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret"; - Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; - Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret"; - Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; - Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret"; - Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; - Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass"; - Preamble += "(const char *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; - Preamble += "(struct objc_class *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass"; - Preamble += "(const char *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match"; - Preamble += "(struct objc_class *, struct objc_object *);\n"; - // @synchronized hooks. - Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n"; - Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; - Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; - Preamble += "struct __objcFastEnumerationState {\n\t"; - Preamble += "unsigned long state;\n\t"; - Preamble += "void **itemsPtr;\n\t"; - Preamble += "unsigned long *mutationsPtr;\n\t"; - Preamble += "unsigned long extra[5];\n};\n"; - Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; - Preamble += "#define __FASTENUMERATIONSTATE\n"; - Preamble += "#endif\n"; - Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; - Preamble += "struct __NSConstantStringImpl {\n"; - Preamble += " int *isa;\n"; - Preamble += " int flags;\n"; - Preamble += " char *str;\n"; - Preamble += " long length;\n"; - Preamble += "};\n"; - Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; - Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; - Preamble += "#else\n"; - Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; - Preamble += "#endif\n"; - Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; - Preamble += "#endif\n"; - // Blocks preamble. - Preamble += "#ifndef BLOCK_IMPL\n"; - Preamble += "#define BLOCK_IMPL\n"; - Preamble += "struct __block_impl {\n"; - Preamble += " void *isa;\n"; - Preamble += " int Flags;\n"; - Preamble += " int Reserved;\n"; - Preamble += " void *FuncPtr;\n"; - Preamble += "};\n"; - Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; - Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; - Preamble += "extern \"C\" __declspec(dllexport) " - "void _Block_object_assign(void *, const void *, const int);\n"; - Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; - Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; - Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; - Preamble += "#else\n"; - Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; - Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; - Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; - Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; - Preamble += "#endif\n"; - Preamble += "#endif\n"; - if (LangOpts.MicrosoftExt) { - Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; - Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; - Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. - Preamble += "#define __attribute__(X)\n"; - Preamble += "#endif\n"; - Preamble += "#define __weak\n"; - } - else { - Preamble += "#define __block\n"; - Preamble += "#define __weak\n"; - } - // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long - // as this avoids warning in any 64bit/32bit compilation model. - Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; + Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts()); } - //===----------------------------------------------------------------------===// // Top Level Driver Code //===----------------------------------------------------------------------===// @@ -722,33 +659,57 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { ConstantStringClassReference = FVD; return; } - } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) { - RewriteInterfaceDecl(MD); + } else if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) { + if (ID->isThisDeclarationADefinition()) + RewriteInterfaceDecl(ID); } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { RewriteCategoryDecl(CD); } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) { - RewriteProtocolDecl(PD); - } else if (ObjCForwardProtocolDecl *FP = - dyn_cast<ObjCForwardProtocolDecl>(D)){ - RewriteForwardProtocolDecl(FP); + if (PD->isThisDeclarationADefinition()) + RewriteProtocolDecl(PD); } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { // Recurse into linkage specifications for (DeclContext::decl_iterator DI = LSD->decls_begin(), DIEnd = LSD->decls_end(); DI != DIEnd; ) { - if (isa<ObjCClassDecl>((*DI))) { - SmallVector<Decl *, 8> DG; - Decl *D = (*DI); - SourceLocation Loc = D->getLocation(); - while (DI != DIEnd && - isa<ObjCClassDecl>(D) && D->getLocation() == Loc) { - DG.push_back(D); - ++DI; - D = (*DI); + if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>((*DI))) { + if (!IFace->isThisDeclarationADefinition()) { + SmallVector<Decl *, 8> DG; + SourceLocation StartLoc = IFace->getLocStart(); + do { + if (isa<ObjCInterfaceDecl>(*DI) && + !cast<ObjCInterfaceDecl>(*DI)->isThisDeclarationADefinition() && + StartLoc == (*DI)->getLocStart()) + DG.push_back(*DI); + else + break; + + ++DI; + } while (DI != DIEnd); + RewriteForwardClassDecl(DG); + continue; + } + } + + if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>((*DI))) { + if (!Proto->isThisDeclarationADefinition()) { + SmallVector<Decl *, 8> DG; + SourceLocation StartLoc = Proto->getLocStart(); + do { + if (isa<ObjCProtocolDecl>(*DI) && + !cast<ObjCProtocolDecl>(*DI)->isThisDeclarationADefinition() && + StartLoc == (*DI)->getLocStart()) + DG.push_back(*DI); + else + break; + + ++DI; + } while (DI != DIEnd); + RewriteForwardProtocolDecl(DG); + continue; } - RewriteForwardClassDecl(DG); - continue; } + HandleTopLevelSingleDecl(*DI); ++DI; } @@ -868,7 +829,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, Getr += ";\n"; Getr += "return (_TYPE)"; Getr += "objc_getProperty(self, _cmd, "; - SynthesizeIvarOffsetComputation(OID, Getr); + RewriteIvarOffsetComputation(OID, Getr); Getr += ", 1)"; } else @@ -898,7 +859,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, // See objc-act.c:objc_synthesize_new_setter() for details. if (GenSetProperty) { Setr += "objc_setProperty (self, _cmd, "; - SynthesizeIvarOffsetComputation(OID, Setr); + RewriteIvarOffsetComputation(OID, Setr); Setr += ", (id)"; Setr += PD->getName(); Setr += ", "; @@ -932,9 +893,9 @@ static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, typedefString += ";\n#endif\n"; } -void RewriteObjC::RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, +void RewriteObjC::RewriteForwardClassEpilogue(ObjCInterfaceDecl *ClassDecl, const std::string &typedefString) { - SourceLocation startLoc = ClassDecl->getLocation(); + SourceLocation startLoc = ClassDecl->getLocStart(); const char *startBuf = SM->getCharacterData(startLoc); const char *semiPtr = strchr(startBuf, ';'); // Replace the @class with typedefs corresponding to the classes. @@ -944,8 +905,7 @@ void RewriteObjC::RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) { std::string typedefString; for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { - ObjCClassDecl *ClassDecl = cast<ObjCClassDecl>(*I); - ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl(); + ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(*I); if (I == D.begin()) { // Translate to typedef's that forward reference structs with the same name // as the class. As a convenience, we include the original declaration @@ -957,15 +917,14 @@ void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) { RewriteOneForwardClassDecl(ForwardDecl, typedefString); } DeclGroupRef::iterator I = D.begin(); - RewriteForwardClassEpilogue(cast<ObjCClassDecl>(*I), typedefString); + RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(*I), typedefString); } void RewriteObjC::RewriteForwardClassDecl( const llvm::SmallVector<Decl*, 8> &D) { std::string typedefString; for (unsigned i = 0; i < D.size(); i++) { - ObjCClassDecl *ClassDecl = cast<ObjCClassDecl>(D[i]); - ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl(); + ObjCInterfaceDecl *ForwardDecl = cast<ObjCInterfaceDecl>(D[i]); if (i == 0) { typedefString += "// @class "; typedefString += ForwardDecl->getNameAsString(); @@ -973,7 +932,7 @@ void RewriteObjC::RewriteForwardClassDecl( } RewriteOneForwardClassDecl(ForwardDecl, typedefString); } - RewriteForwardClassEpilogue(cast<ObjCClassDecl>(D[0]), typedefString); + RewriteForwardClassEpilogue(cast<ObjCInterfaceDecl>(D[0]), typedefString); } void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { @@ -1026,7 +985,8 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { SourceLocation LocStart = PDecl->getLocStart(); - + assert(PDecl->isThisDeclarationADefinition()); + // FIXME: handle protocol headers that are declared across multiple lines. ReplaceText(LocStart, 0, "// "); @@ -1064,8 +1024,17 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { } } -void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) { - SourceLocation LocStart = PDecl->getLocation(); +void RewriteObjC::RewriteForwardProtocolDecl(DeclGroupRef D) { + SourceLocation LocStart = (*D.begin())->getLocStart(); + if (LocStart.isInvalid()) + llvm_unreachable("Invalid SourceLocation"); + // FIXME: handle forward protocol that are declared across multiple lines. + ReplaceText(LocStart, 0, "// "); +} + +void +RewriteObjC::RewriteForwardProtocolDecl(const llvm::SmallVector<Decl*, 8> &DG) { + SourceLocation LocStart = DG[0]->getLocStart(); if (LocStart.isInvalid()) llvm_unreachable("Invalid SourceLocation"); // FIXME: handle forward protocol that are declared across multiple lines. @@ -1168,10 +1137,8 @@ void RewriteObjC::RewriteObjCMethodDecl(const ObjCInterfaceDecl *IDecl, std::string Name = PDecl->getNameAsString(); QualType QT = PDecl->getType(); // Make sure we convert "t (^)(...)" to "t (*)(...)". - if (convertBlockPointerToFunctionPointer(QT)) - QT.getAsStringInternal(Name, Context->getPrintingPolicy()); - else - PDecl->getType().getAsStringInternal(Name, Context->getPrintingPolicy()); + (void)convertBlockPointerToFunctionPointer(QT); + QT.getAsStringInternal(Name, Context->getPrintingPolicy()); ResultStr += Name; } } @@ -1248,7 +1215,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { std::string ResultStr; - if (!ObjCForwardDecls.count(ClassDecl)) { + if (!ObjCForwardDecls.count(ClassDecl->getCanonicalDecl())) { // we haven't seen a forward decl - generate a typedef. ResultStr = "#ifndef _REWRITER_typedef_"; ResultStr += ClassDecl->getNameAsString(); @@ -1260,9 +1227,9 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { ResultStr += ClassDecl->getNameAsString(); ResultStr += ";\n#endif\n"; // Mark this typedef as having been generated. - ObjCForwardDecls.insert(ClassDecl); + ObjCForwardDecls.insert(ClassDecl->getCanonicalDecl()); } - SynthesizeObjCInternalStruct(ClassDecl, ResultStr); + RewriteObjCInternalStruct(ClassDecl, ResultStr); for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), E = ClassDecl->prop_end(); I != E; ++I) @@ -1281,287 +1248,163 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { "/* @end */"); } -Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(BinaryOperator *BinOp, Expr *newStmt, - SourceRange SrcRange) { - ObjCMethodDecl *OMD = 0; - QualType Ty; - Selector Sel; - Stmt *Receiver = 0; - bool Super = false; - QualType SuperTy; - SourceLocation SuperLocation; - SourceLocation SelectorLoc; - // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ObjCImplicitSetterGetterRefExpr. - // This allows us to reuse all the fun and games in SynthMessageExpr(). - if (ObjCPropertyRefExpr *PropRefExpr = - dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS())) { - SelectorLoc = PropRefExpr->getLocation(); - if (PropRefExpr->isExplicitProperty()) { - ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty(); - OMD = PDecl->getSetterMethodDecl(); - Ty = PDecl->getType(); - Sel = PDecl->getSetterName(); - } else { - OMD = PropRefExpr->getImplicitPropertySetter(); - Sel = OMD->getSelector(); - Ty = PropRefExpr->getType(); - } - Super = PropRefExpr->isSuperReceiver(); - if (!Super) { - Receiver = PropRefExpr->getBase(); - } else { - SuperTy = PropRefExpr->getSuperReceiverType(); - SuperLocation = PropRefExpr->getReceiverLocation(); - } - } - - assert(OMD && "RewritePropertyOrImplicitSetter - null OMD"); - - ObjCMessageExpr *MsgExpr; - if (Super) - MsgExpr = ObjCMessageExpr::Create(*Context, - Ty.getNonReferenceType(), - Expr::getValueKindForType(Ty), - /*FIXME?*/SourceLocation(), - SuperLocation, - /*IsInstanceSuper=*/true, - SuperTy, - Sel, SelectorLoc, OMD, - newStmt, - /*FIXME:*/SourceLocation()); - else { - // FIXME. Refactor this into common code with that in - // RewritePropertyOrImplicitGetter - assert(Receiver && "RewritePropertyOrImplicitSetter - null Receiver"); - if (Expr *Exp = dyn_cast<Expr>(Receiver)) - if (PropGetters[Exp]) - // This allows us to handle chain/nested property/implicit getters. - Receiver = PropGetters[Exp]; - - MsgExpr = ObjCMessageExpr::Create(*Context, - Ty.getNonReferenceType(), - Expr::getValueKindForType(Ty), - /*FIXME: */SourceLocation(), - cast<Expr>(Receiver), - Sel, SelectorLoc, OMD, - newStmt, - /*FIXME:*/SourceLocation()); - } - Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr); +Stmt *RewriteObjC::RewritePropertyOrImplicitSetter(PseudoObjectExpr *PseudoOp) { + SourceRange OldRange = PseudoOp->getSourceRange(); - // Now do the actual rewrite. - ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange); - //delete BinOp; - // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references - // to things that stay around. - Context->Deallocate(MsgExpr); - return ReplacingStmt; -} + // We just magically know some things about the structure of this + // expression. + ObjCMessageExpr *OldMsg = + cast<ObjCMessageExpr>(PseudoOp->getSemanticExpr( + PseudoOp->getNumSemanticExprs() - 1)); -Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(Expr *PropOrGetterRefExpr) { - // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr or ImplicitGetter. - // This allows us to reuse all the fun and games in SynthMessageExpr(). - Stmt *Receiver = 0; - ObjCMethodDecl *OMD = 0; - QualType Ty; - Selector Sel; - bool Super = false; - QualType SuperTy; - SourceLocation SuperLocation; - SourceLocation SelectorLoc; - if (ObjCPropertyRefExpr *PropRefExpr = - dyn_cast<ObjCPropertyRefExpr>(PropOrGetterRefExpr)) { - SelectorLoc = PropRefExpr->getLocation(); - if (PropRefExpr->isExplicitProperty()) { - ObjCPropertyDecl *PDecl = PropRefExpr->getExplicitProperty(); - OMD = PDecl->getGetterMethodDecl(); - Ty = PDecl->getType(); - Sel = PDecl->getGetterName(); - } else { - OMD = PropRefExpr->getImplicitPropertyGetter(); - Sel = OMD->getSelector(); - Ty = PropRefExpr->getType(); - } - Super = PropRefExpr->isSuperReceiver(); - if (!Super) - Receiver = PropRefExpr->getBase(); - else { - SuperTy = PropRefExpr->getSuperReceiverType(); - SuperLocation = PropRefExpr->getReceiverLocation(); - } - } - - assert (OMD && "RewritePropertyOrImplicitGetter - OMD is null"); - - ObjCMessageExpr *MsgExpr; - if (Super) - MsgExpr = ObjCMessageExpr::Create(*Context, - Ty.getNonReferenceType(), - Expr::getValueKindForType(Ty), - PropOrGetterRefExpr->getLocStart(), - SuperLocation, - /*IsInstanceSuper=*/true, - SuperTy, - Sel, SelectorLoc, OMD, - ArrayRef<Expr*>(), - PropOrGetterRefExpr->getLocEnd()); - else { - assert (Receiver && "RewritePropertyOrImplicitGetter - Receiver is null"); - if (Expr *Exp = dyn_cast<Expr>(Receiver)) - if (PropGetters[Exp]) - // This allows us to handle chain/nested property/implicit getters. - Receiver = PropGetters[Exp]; - MsgExpr = ObjCMessageExpr::Create(*Context, - Ty.getNonReferenceType(), - Expr::getValueKindForType(Ty), - PropOrGetterRefExpr->getLocStart(), - cast<Expr>(Receiver), - Sel, SelectorLoc, OMD, - ArrayRef<Expr*>(), - PropOrGetterRefExpr->getLocEnd()); - } - - Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr, MsgExpr->getLocStart(), - MsgExpr->getLocEnd()); - - if (!PropParentMap) - PropParentMap = new ParentMap(CurrentBody); - bool NestedPropertyRef = false; - Stmt *Parent = PropParentMap->getParent(PropOrGetterRefExpr); - ImplicitCastExpr*ICE=0; - if (Parent) - if ((ICE = dyn_cast<ImplicitCastExpr>(Parent))) { - assert((ICE->getCastKind() == CK_GetObjCProperty) - && "RewritePropertyOrImplicitGetter"); - Parent = PropParentMap->getParent(Parent); - NestedPropertyRef = (Parent && isa<ObjCPropertyRefExpr>(Parent)); + // Because the rewriter doesn't allow us to rewrite rewritten code, + // we need to suppress rewriting the sub-statements. + Expr *Base, *RHS; + { + DisableReplaceStmtScope S(*this); + + // Rebuild the base expression if we have one. + Base = 0; + if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { + Base = OldMsg->getInstanceReceiver(); + Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); + Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); } - if (NestedPropertyRef) { - // We stash away the ReplacingStmt since actually doing the - // replacement/rewrite won't work for nested getters (e.g. obj.p.i) - PropGetters[ICE] = ReplacingStmt; - // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references - // to things that stay around. - Context->Deallocate(MsgExpr); - return PropOrGetterRefExpr; // return the original... - } else { - ReplaceStmt(PropOrGetterRefExpr, ReplacingStmt); - // delete PropRefExpr; elsewhere... - // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references - // to things that stay around. - Context->Deallocate(MsgExpr); - return ReplacingStmt; + + // Rebuild the RHS. + RHS = cast<BinaryOperator>(PseudoOp->getSyntacticForm())->getRHS(); + RHS = cast<OpaqueValueExpr>(RHS)->getSourceExpr(); + RHS = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(RHS)); + } + + // TODO: avoid this copy. + SmallVector<SourceLocation, 1> SelLocs; + OldMsg->getSelectorLocs(SelLocs); + + ObjCMessageExpr *NewMsg = 0; + switch (OldMsg->getReceiverKind()) { + case ObjCMessageExpr::Class: + NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), + OldMsg->getValueKind(), + OldMsg->getLeftLoc(), + OldMsg->getClassReceiverTypeInfo(), + OldMsg->getSelector(), + SelLocs, + OldMsg->getMethodDecl(), + RHS, + OldMsg->getRightLoc(), + OldMsg->isImplicit()); + break; + + case ObjCMessageExpr::Instance: + NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), + OldMsg->getValueKind(), + OldMsg->getLeftLoc(), + Base, + OldMsg->getSelector(), + SelLocs, + OldMsg->getMethodDecl(), + RHS, + OldMsg->getRightLoc(), + OldMsg->isImplicit()); + break; + + case ObjCMessageExpr::SuperClass: + case ObjCMessageExpr::SuperInstance: + NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), + OldMsg->getValueKind(), + OldMsg->getLeftLoc(), + OldMsg->getSuperLoc(), + OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, + OldMsg->getSuperType(), + OldMsg->getSelector(), + SelLocs, + OldMsg->getMethodDecl(), + RHS, + OldMsg->getRightLoc(), + OldMsg->isImplicit()); + break; } + + Stmt *Replacement = SynthMessageExpr(NewMsg); + ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); + return Replacement; } -Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, - SourceLocation OrigStart, - bool &replaced) { - ObjCIvarDecl *D = IV->getDecl(); - const Expr *BaseExpr = IV->getBase(); - if (CurMethodDef) { - if (BaseExpr->getType()->isObjCObjectPointerType()) { - const ObjCInterfaceType *iFaceDecl = - dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); - assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); - // lookup which class implements the instance variable. - ObjCInterfaceDecl *clsDeclared = 0; - iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), - clsDeclared); - assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); +Stmt *RewriteObjC::RewritePropertyOrImplicitGetter(PseudoObjectExpr *PseudoOp) { + SourceRange OldRange = PseudoOp->getSourceRange(); - // Synthesize an explicit cast to gain access to the ivar. - std::string RecName = clsDeclared->getIdentifier()->getName(); - RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName); - RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), SourceLocation(), - II); - assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); - QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); - CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, - CK_BitCast, - IV->getBase()); - // Don't forget the parens to enforce the proper binding. - ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), - IV->getBase()->getLocEnd(), - castExpr); - replaced = true; - if (IV->isFreeIvar() && - CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) { - MemberExpr *ME = new (Context) MemberExpr(PE, true, D, - IV->getLocation(), - D->getType(), - VK_LValue, OK_Ordinary); - // delete IV; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. - return ME; - } - // Get the new text - // Cannot delete IV->getBase(), since PE points to it. - // Replace the old base with the cast. This is important when doing - // embedded rewrites. For example, [newInv->_container addObject:0]. - IV->setBase(PE); - return IV; - } - } else { // we are outside a method. - assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); + // We just magically know some things about the structure of this + // expression. + ObjCMessageExpr *OldMsg = + cast<ObjCMessageExpr>(PseudoOp->getResultExpr()->IgnoreImplicit()); - // Explicit ivar refs need to have a cast inserted. - // FIXME: consider sharing some of this code with the code above. - if (BaseExpr->getType()->isObjCObjectPointerType()) { - const ObjCInterfaceType *iFaceDecl = - dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); - // lookup which class implements the instance variable. - ObjCInterfaceDecl *clsDeclared = 0; - iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), - clsDeclared); - assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); + // Because the rewriter doesn't allow us to rewrite rewritten code, + // we need to suppress rewriting the sub-statements. + Expr *Base = 0; + { + DisableReplaceStmtScope S(*this); - // Synthesize an explicit cast to gain access to the ivar. - std::string RecName = clsDeclared->getIdentifier()->getName(); - RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName); - RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, - SourceLocation(), SourceLocation(), - II); - assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); - QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); - CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, - CK_BitCast, - IV->getBase()); - // Don't forget the parens to enforce the proper binding. - ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), - IV->getBase()->getLocEnd(), castExpr); - replaced = true; - // Cannot delete IV->getBase(), since PE points to it. - // Replace the old base with the cast. This is important when doing - // embedded rewrites. For example, [newInv->_container addObject:0]. - IV->setBase(PE); - return IV; + // Rebuild the base expression if we have one. + if (OldMsg->getReceiverKind() == ObjCMessageExpr::Instance) { + Base = OldMsg->getInstanceReceiver(); + Base = cast<OpaqueValueExpr>(Base)->getSourceExpr(); + Base = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(Base)); } } - return IV; -} -Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) { - for (Stmt::child_range CI = S->children(); CI; ++CI) { - if (*CI) { - Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced); - if (newStmt) - *CI = newStmt; - } - } - if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { - SourceRange OrigStmtRange = S->getSourceRange(); - Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(), - replaced); - return newStmt; - } - if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) { - Stmt *newStmt = SynthMessageExpr(MsgRefExpr); - return newStmt; + // Intentionally empty. + SmallVector<SourceLocation, 1> SelLocs; + SmallVector<Expr*, 1> Args; + + ObjCMessageExpr *NewMsg = 0; + switch (OldMsg->getReceiverKind()) { + case ObjCMessageExpr::Class: + NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), + OldMsg->getValueKind(), + OldMsg->getLeftLoc(), + OldMsg->getClassReceiverTypeInfo(), + OldMsg->getSelector(), + SelLocs, + OldMsg->getMethodDecl(), + Args, + OldMsg->getRightLoc(), + OldMsg->isImplicit()); + break; + + case ObjCMessageExpr::Instance: + NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), + OldMsg->getValueKind(), + OldMsg->getLeftLoc(), + Base, + OldMsg->getSelector(), + SelLocs, + OldMsg->getMethodDecl(), + Args, + OldMsg->getRightLoc(), + OldMsg->isImplicit()); + break; + + case ObjCMessageExpr::SuperClass: + case ObjCMessageExpr::SuperInstance: + NewMsg = ObjCMessageExpr::Create(*Context, OldMsg->getType(), + OldMsg->getValueKind(), + OldMsg->getLeftLoc(), + OldMsg->getSuperLoc(), + OldMsg->getReceiverKind() == ObjCMessageExpr::SuperInstance, + OldMsg->getSuperType(), + OldMsg->getSelector(), + SelLocs, + OldMsg->getMethodDecl(), + Args, + OldMsg->getRightLoc(), + OldMsg->isImplicit()); + break; } - return S; + + Stmt *Replacement = SynthMessageExpr(NewMsg); + ReplaceStmtWithRange(PseudoOp, Replacement, OldRange); + return Replacement; } /// SynthCountByEnumWithState - To print: @@ -1571,7 +1414,7 @@ Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) { /// sel_registerName( /// "countByEnumeratingWithState:objects:count:"), /// &enumState, -/// (id *)items, (unsigned int)16) +/// (id *)__rw_items, (unsigned int)16) /// void RewriteObjC::SynthCountByEnumWithState(std::string &buf) { buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, " @@ -1581,7 +1424,7 @@ void RewriteObjC::SynthCountByEnumWithState(std::string &buf) { buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),"; buf += "\n\t\t"; buf += "&enumState, " - "(id *)items, (unsigned int)16)"; + "(id *)__rw_items, (unsigned int)16)"; } /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach @@ -1626,10 +1469,10 @@ Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { /// { /// type elem; /// struct __objcFastEnumerationState enumState = { 0 }; -/// id items[16]; +/// id __rw_items[16]; /// id l_collection = (id)collection; /// unsigned long limit = [l_collection countByEnumeratingWithState:&enumState -/// objects:items count:16]; +/// objects:__rw_items count:16]; /// if (limit) { /// unsigned long startMutations = *enumState.mutationsPtr; /// do { @@ -1642,7 +1485,7 @@ Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { /// __continue_label: ; /// } while (counter < limit); /// } while (limit = [l_collection countByEnumeratingWithState:&enumState -/// objects:items count:16]); +/// objects:__rw_items count:16]); /// elem = nil; /// __break_label: ; /// } @@ -1694,8 +1537,8 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, // struct __objcFastEnumerationState enumState = { 0 }; buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t"; - // id items[16]; - buf += "id items[16];\n\t"; + // id __rw_items[16]; + buf += "id __rw_items[16];\n\t"; // id l_collection = (id) buf += "id l_collection = (id)"; // Find start location of 'collection' the hard way! @@ -1720,7 +1563,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, buf = ";\n\t"; // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState - // objects:items count:16]; + // objects:__rw_items count:16]; // which is synthesized into: // unsigned int limit = // ((unsigned int (*) @@ -1729,7 +1572,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, // sel_registerName( // "countByEnumeratingWithState:objects:count:"), // (struct __objcFastEnumerationState *)&state, - // (id *)items, (unsigned int)16); + // (id *)__rw_items, (unsigned int)16); buf += "unsigned long limit =\n\t\t"; SynthCountByEnumWithState(buf); buf += ";\n\t"; @@ -1758,7 +1601,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, /// __continue_label: ; /// } while (counter < limit); /// } while (limit = [l_collection countByEnumeratingWithState:&enumState - /// objects:items count:16]); + /// objects:__rw_items count:16]); /// elem = nil; /// __break_label: ; /// } @@ -2200,8 +2043,8 @@ CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl( QualType msgSendType = FD->getType(); // Create a reference to the objc_msgSend() declaration. - DeclRefExpr *DRE = - new (Context) DeclRefExpr(FD, msgSendType, VK_LValue, SourceLocation()); + DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, msgSendType, + VK_LValue, SourceLocation()); // Now, we cast the reference to a pointer to the objc_msgSend type. QualType pToFunc = Context->getPointerType(msgSendType); @@ -2667,7 +2510,7 @@ void RewriteObjC::SynthGetSuperClassFunctionDecl() { false); } -// SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name); +// SynthGetMetaClassFunctionDecl - id objc_getMetaClass(const char *name); void RewriteObjC::SynthGetMetaClassFunctionDecl() { IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass"); SmallVector<QualType, 16> ArgTys; @@ -2714,7 +2557,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), &Context->Idents.get(S), strType, 0, SC_Static, SC_None); - DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, VK_LValue, + DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, false, strType, VK_LValue, SourceLocation()); Expr *Unop = new (Context) UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()), @@ -2842,6 +2685,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), CK_BitCast, new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), + false, Context->getObjCIdType(), VK_RValue, SourceLocation())) @@ -2862,7 +2706,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, // (Class)objc_getClass("CurrentClass") CastExpr *ArgExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCClassType(), - CK_CPointerToObjCPointerCast, Cls); + CK_BitCast, Cls); ClsExprs.clear(); ClsExprs.push_back(ArgExpr); Cls = SynthesizeCallToFunctionDecl(GetSuperClassFunctionDecl, @@ -2883,7 +2727,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SynthSuperContructorFunctionDecl(); // Simulate a contructor call... DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, - superType, VK_LValue, + false, superType, VK_LValue, SourceLocation()); SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(), @@ -2953,6 +2797,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(), CK_BitCast, new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), + false, Context->getObjCIdType(), VK_RValue, SourceLocation())) ); // set the 'receiver'. @@ -2992,7 +2837,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, SynthSuperContructorFunctionDecl(); // Simulate a contructor call... DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl, - superType, VK_LValue, + false, superType, VK_LValue, SourceLocation()); SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0], InitExprs.size(), @@ -3144,7 +2989,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, QualType msgSendType = MsgSendFlavor->getType(); // Create a reference to the objc_msgSend() declaration. - DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType, + DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, false, msgSendType, VK_LValue, SourceLocation()); // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid). @@ -3180,7 +3025,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp, // method's return type. // Create a reference to the objc_msgSend_stret() declaration. - DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType, + DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, + false, msgSendType, VK_LValue, SourceLocation()); // Need to cast objc_msgSend_stret to "void *" (see above comment). cast = NoTypeInfoCStyleCastExpr(Context, @@ -3268,8 +3114,8 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), SourceLocation(), ID, getProtocolType(), 0, SC_Extern, SC_None); - DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), VK_LValue, - SourceLocation()); + DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, false, getProtocolType(), + VK_LValue, SourceLocation()); Expr *DerefExpr = new (Context) UnaryOperator(DRE, UO_AddrOf, Context->getPointerType(DRE->getType()), VK_RValue, OK_Ordinary, SourceLocation()); @@ -3277,7 +3123,7 @@ Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { CK_BitCast, DerefExpr); ReplaceStmt(Exp, castExpr); - ProtocolExprDecls.insert(Exp->getProtocol()); + ProtocolExprDecls.insert(Exp->getProtocol()->getCanonicalDecl()); // delete Exp; leak for now, see RewritePropertyOrImplicitSetter() usage for more info. return castExpr; @@ -3309,9 +3155,9 @@ bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, return false; } -/// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to +/// RewriteObjCInternalStruct - Rewrite one internal struct corresponding to /// an objective-c class with ivars. -void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, +void RewriteObjC::RewriteObjCInternalStruct(ObjCInterfaceDecl *CDecl, std::string &Result) { assert(CDecl && "Class missing in SynthesizeObjCInternalStruct"); assert(CDecl->getName() != "" && @@ -3322,14 +3168,14 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass(); int NumIvars = CDecl->ivar_size(); SourceLocation LocStart = CDecl->getLocStart(); - SourceLocation LocEnd = CDecl->getLocEnd(); + SourceLocation LocEnd = CDecl->getEndOfDefinitionLoc(); const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); // If no ivars and no root or if its root, directly or indirectly, // have no ivars (thus not synthesized) then no need to synthesize this class. - if ((CDecl->isForwardDecl() || NumIvars == 0) && + if ((!CDecl->isThisDeclarationADefinition() || NumIvars == 0) && (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); ReplaceText(LocStart, endBuf-startBuf, Result); @@ -3441,667 +3287,10 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, llvm_unreachable("struct already synthesize- SynthesizeObjCInternalStruct"); } -// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or -/// class methods. -template<typename MethodIterator> -void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, - MethodIterator MethodEnd, - bool IsInstanceMethod, - StringRef prefix, - StringRef ClassName, - std::string &Result) { - if (MethodBegin == MethodEnd) return; - - if (!objc_impl_method) { - /* struct _objc_method { - SEL _cmd; - char *method_types; - void *_imp; - } - */ - Result += "\nstruct _objc_method {\n"; - Result += "\tSEL _cmd;\n"; - Result += "\tchar *method_types;\n"; - Result += "\tvoid *_imp;\n"; - Result += "};\n"; - - objc_impl_method = true; - } - - // Build _objc_method_list for class's methods if needed - - /* struct { - struct _objc_method_list *next_method; - int method_count; - struct _objc_method method_list[]; - } - */ - unsigned NumMethods = std::distance(MethodBegin, MethodEnd); - Result += "\nstatic struct {\n"; - Result += "\tstruct _objc_method_list *next_method;\n"; - Result += "\tint method_count;\n"; - Result += "\tstruct _objc_method method_list["; - Result += utostr(NumMethods); - Result += "];\n} _OBJC_"; - Result += prefix; - Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; - Result += "_METHODS_"; - Result += ClassName; - Result += " __attribute__ ((used, section (\"__OBJC, __"; - Result += IsInstanceMethod ? "inst" : "cls"; - Result += "_meth\")))= "; - Result += "{\n\t0, " + utostr(NumMethods) + "\n"; - - Result += "\t,{{(SEL)\""; - Result += (*MethodBegin)->getSelector().getAsString().c_str(); - std::string MethodTypeString; - Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); - Result += "\", \""; - Result += MethodTypeString; - Result += "\", (void *)"; - Result += MethodInternalNames[*MethodBegin]; - Result += "}\n"; - for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { - Result += "\t ,{(SEL)\""; - Result += (*MethodBegin)->getSelector().getAsString().c_str(); - std::string MethodTypeString; - Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); - Result += "\", \""; - Result += MethodTypeString; - Result += "\", (void *)"; - Result += MethodInternalNames[*MethodBegin]; - Result += "}\n"; - } - Result += "\t }\n};\n"; -} - -/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. -void RewriteObjC:: -RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, StringRef prefix, - StringRef ClassName, std::string &Result) { - static bool objc_protocol_methods = false; - - // Output struct protocol_methods holder of method selector and type. - if (!objc_protocol_methods && !PDecl->isForwardDecl()) { - /* struct protocol_methods { - SEL _cmd; - char *method_types; - } - */ - Result += "\nstruct _protocol_methods {\n"; - Result += "\tstruct objc_selector *_cmd;\n"; - Result += "\tchar *method_types;\n"; - Result += "};\n"; - - objc_protocol_methods = true; - } - // Do not synthesize the protocol more than once. - if (ObjCSynthesizedProtocols.count(PDecl)) - return; - - if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { - unsigned NumMethods = std::distance(PDecl->instmeth_begin(), - PDecl->instmeth_end()); - /* struct _objc_protocol_method_list { - int protocol_method_count; - struct protocol_methods protocols[]; - } - */ - Result += "\nstatic struct {\n"; - Result += "\tint protocol_method_count;\n"; - Result += "\tstruct _protocol_methods protocol_methods["; - Result += utostr(NumMethods); - Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_"; - Result += PDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " - "{\n\t" + utostr(NumMethods) + "\n"; - - // Output instance methods declared in this protocol. - for (ObjCProtocolDecl::instmeth_iterator - I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); - I != E; ++I) { - if (I == PDecl->instmeth_begin()) - Result += "\t ,{{(struct objc_selector *)\""; - else - Result += "\t ,{(struct objc_selector *)\""; - Result += (*I)->getSelector().getAsString(); - std::string MethodTypeString; - Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); - Result += "\", \""; - Result += MethodTypeString; - Result += "\"}\n"; - } - Result += "\t }\n};\n"; - } - - // Output class methods declared in this protocol. - unsigned NumMethods = std::distance(PDecl->classmeth_begin(), - PDecl->classmeth_end()); - if (NumMethods > 0) { - /* struct _objc_protocol_method_list { - int protocol_method_count; - struct protocol_methods protocols[]; - } - */ - Result += "\nstatic struct {\n"; - Result += "\tint protocol_method_count;\n"; - Result += "\tstruct _protocol_methods protocol_methods["; - Result += utostr(NumMethods); - Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_"; - Result += PDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " - "{\n\t"; - Result += utostr(NumMethods); - Result += "\n"; - - // Output instance methods declared in this protocol. - for (ObjCProtocolDecl::classmeth_iterator - I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); - I != E; ++I) { - if (I == PDecl->classmeth_begin()) - Result += "\t ,{{(struct objc_selector *)\""; - else - Result += "\t ,{(struct objc_selector *)\""; - Result += (*I)->getSelector().getAsString(); - std::string MethodTypeString; - Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); - Result += "\", \""; - Result += MethodTypeString; - Result += "\"}\n"; - } - Result += "\t }\n};\n"; - } - - // Output: - /* struct _objc_protocol { - // Objective-C 1.0 extensions - struct _objc_protocol_extension *isa; - char *protocol_name; - struct _objc_protocol **protocol_list; - struct _objc_protocol_method_list *instance_methods; - struct _objc_protocol_method_list *class_methods; - }; - */ - static bool objc_protocol = false; - if (!objc_protocol) { - Result += "\nstruct _objc_protocol {\n"; - Result += "\tstruct _objc_protocol_extension *isa;\n"; - Result += "\tchar *protocol_name;\n"; - Result += "\tstruct _objc_protocol **protocol_list;\n"; - Result += "\tstruct _objc_protocol_method_list *instance_methods;\n"; - Result += "\tstruct _objc_protocol_method_list *class_methods;\n"; - Result += "};\n"; - - objc_protocol = true; - } - - Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_"; - Result += PDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= " - "{\n\t0, \""; - Result += PDecl->getNameAsString(); - Result += "\", 0, "; - if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { - Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; - Result += PDecl->getNameAsString(); - Result += ", "; - } - else - Result += "0, "; - if (PDecl->classmeth_begin() != PDecl->classmeth_end()) { - Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; - Result += PDecl->getNameAsString(); - Result += "\n"; - } - else - Result += "0\n"; - Result += "};\n"; - - // Mark this protocol as having been generated. - if (!ObjCSynthesizedProtocols.insert(PDecl)) - llvm_unreachable("protocol already synthesized"); - -} - -void RewriteObjC:: -RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, - StringRef prefix, StringRef ClassName, - std::string &Result) { - if (Protocols.empty()) return; - - for (unsigned i = 0; i != Protocols.size(); i++) - RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result); - - // Output the top lovel protocol meta-data for the class. - /* struct _objc_protocol_list { - struct _objc_protocol_list *next; - int protocol_count; - struct _objc_protocol *class_protocols[]; - } - */ - Result += "\nstatic struct {\n"; - Result += "\tstruct _objc_protocol_list *next;\n"; - Result += "\tint protocol_count;\n"; - Result += "\tstruct _objc_protocol *class_protocols["; - Result += utostr(Protocols.size()); - Result += "];\n} _OBJC_"; - Result += prefix; - Result += "_PROTOCOLS_"; - Result += ClassName; - Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " - "{\n\t0, "; - Result += utostr(Protocols.size()); - Result += "\n"; - - Result += "\t,{&_OBJC_PROTOCOL_"; - Result += Protocols[0]->getNameAsString(); - Result += " \n"; - - for (unsigned i = 1; i != Protocols.size(); i++) { - Result += "\t ,&_OBJC_PROTOCOL_"; - Result += Protocols[i]->getNameAsString(); - Result += "\n"; - } - Result += "\t }\n};\n"; -} - - -/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category -/// implementation. -void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, - std::string &Result) { - ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); - // Find category declaration for this implementation. - ObjCCategoryDecl *CDecl; - for (CDecl = ClassDecl->getCategoryList(); CDecl; - CDecl = CDecl->getNextClassCategory()) - if (CDecl->getIdentifier() == IDecl->getIdentifier()) - break; - - std::string FullCategoryName = ClassDecl->getNameAsString(); - FullCategoryName += '_'; - FullCategoryName += IDecl->getNameAsString(); - - // Build _objc_method_list for class's instance methods if needed - SmallVector<ObjCMethodDecl *, 32> - InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); - - // If any of our property implementations have associated getters or - // setters, produce metadata for them as well. - for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), - PropEnd = IDecl->propimpl_end(); - Prop != PropEnd; ++Prop) { - if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) - continue; - if (!(*Prop)->getPropertyIvarDecl()) - continue; - ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); - if (!PD) - continue; - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) - InstanceMethods.push_back(Getter); - if (PD->isReadOnly()) - continue; - if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) - InstanceMethods.push_back(Setter); - } - RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), - true, "CATEGORY_", FullCategoryName.c_str(), - Result); - - // Build _objc_method_list for class's class methods if needed - RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), - false, "CATEGORY_", FullCategoryName.c_str(), - Result); - - // Protocols referenced in class declaration? - // Null CDecl is case of a category implementation with no category interface - if (CDecl) - RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", - FullCategoryName, Result); - /* struct _objc_category { - char *category_name; - char *class_name; - struct _objc_method_list *instance_methods; - struct _objc_method_list *class_methods; - struct _objc_protocol_list *protocols; - // Objective-C 1.0 extensions - uint32_t size; // sizeof (struct _objc_category) - struct _objc_property_list *instance_properties; // category's own - // @property decl. - }; - */ - - static bool objc_category = false; - if (!objc_category) { - Result += "\nstruct _objc_category {\n"; - Result += "\tchar *category_name;\n"; - Result += "\tchar *class_name;\n"; - Result += "\tstruct _objc_method_list *instance_methods;\n"; - Result += "\tstruct _objc_method_list *class_methods;\n"; - Result += "\tstruct _objc_protocol_list *protocols;\n"; - Result += "\tunsigned int size;\n"; - Result += "\tstruct _objc_property_list *instance_properties;\n"; - Result += "};\n"; - objc_category = true; - } - Result += "\nstatic struct _objc_category _OBJC_CATEGORY_"; - Result += FullCategoryName; - Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\""; - Result += IDecl->getNameAsString(); - Result += "\"\n\t, \""; - Result += ClassDecl->getNameAsString(); - Result += "\"\n"; - - if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { - Result += "\t, (struct _objc_method_list *)" - "&_OBJC_CATEGORY_INSTANCE_METHODS_"; - Result += FullCategoryName; - Result += "\n"; - } - else - Result += "\t, 0\n"; - if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { - Result += "\t, (struct _objc_method_list *)" - "&_OBJC_CATEGORY_CLASS_METHODS_"; - Result += FullCategoryName; - Result += "\n"; - } - else - Result += "\t, 0\n"; - - if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) { - Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; - Result += FullCategoryName; - Result += "\n"; - } - else - Result += "\t, 0\n"; - Result += "\t, sizeof(struct _objc_category), 0\n};\n"; -} - -/// SynthesizeIvarOffsetComputation - This rutine synthesizes computation of -/// ivar offset. -void RewriteObjC::SynthesizeIvarOffsetComputation(ObjCIvarDecl *ivar, - std::string &Result) { - if (ivar->isBitField()) { - // FIXME: The hack below doesn't work for bitfields. For now, we simply - // place all bitfields at offset 0. - Result += "0"; - } else { - Result += "__OFFSETOFIVAR__(struct "; - Result += ivar->getContainingInterface()->getNameAsString(); - if (LangOpts.MicrosoftExt) - Result += "_IMPL"; - Result += ", "; - Result += ivar->getNameAsString(); - Result += ")"; - } -} - //===----------------------------------------------------------------------===// // Meta Data Emission //===----------------------------------------------------------------------===// -void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, - std::string &Result) { - ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); - - // Explicitly declared @interface's are already synthesized. - if (CDecl->isImplicitInterfaceDecl()) { - // FIXME: Implementation of a class with no @interface (legacy) doese not - // produce correct synthesis as yet. - SynthesizeObjCInternalStruct(CDecl, Result); - } - - // Build _objc_ivar_list metadata for classes ivars if needed - unsigned NumIvars = !IDecl->ivar_empty() - ? IDecl->ivar_size() - : (CDecl ? CDecl->ivar_size() : 0); - if (NumIvars > 0) { - static bool objc_ivar = false; - if (!objc_ivar) { - /* struct _objc_ivar { - char *ivar_name; - char *ivar_type; - int ivar_offset; - }; - */ - Result += "\nstruct _objc_ivar {\n"; - Result += "\tchar *ivar_name;\n"; - Result += "\tchar *ivar_type;\n"; - Result += "\tint ivar_offset;\n"; - Result += "};\n"; - - objc_ivar = true; - } - - /* struct { - int ivar_count; - struct _objc_ivar ivar_list[nIvars]; - }; - */ - Result += "\nstatic struct {\n"; - Result += "\tint ivar_count;\n"; - Result += "\tstruct _objc_ivar ivar_list["; - Result += utostr(NumIvars); - Result += "];\n} _OBJC_INSTANCE_VARIABLES_"; - Result += IDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " - "{\n\t"; - Result += utostr(NumIvars); - Result += "\n"; - - ObjCInterfaceDecl::ivar_iterator IVI, IVE; - SmallVector<ObjCIvarDecl *, 8> IVars; - if (!IDecl->ivar_empty()) { - for (ObjCInterfaceDecl::ivar_iterator - IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); - IV != IVEnd; ++IV) - IVars.push_back(*IV); - IVI = IDecl->ivar_begin(); - IVE = IDecl->ivar_end(); - } else { - IVI = CDecl->ivar_begin(); - IVE = CDecl->ivar_end(); - } - Result += "\t,{{\""; - Result += (*IVI)->getNameAsString(); - Result += "\", \""; - std::string TmpString, StrEncoding; - Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); - QuoteDoublequotes(TmpString, StrEncoding); - Result += StrEncoding; - Result += "\", "; - SynthesizeIvarOffsetComputation(*IVI, Result); - Result += "}\n"; - for (++IVI; IVI != IVE; ++IVI) { - Result += "\t ,{\""; - Result += (*IVI)->getNameAsString(); - Result += "\", \""; - std::string TmpString, StrEncoding; - Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); - QuoteDoublequotes(TmpString, StrEncoding); - Result += StrEncoding; - Result += "\", "; - SynthesizeIvarOffsetComputation((*IVI), Result); - Result += "}\n"; - } - - Result += "\t }\n};\n"; - } - - // Build _objc_method_list for class's instance methods if needed - SmallVector<ObjCMethodDecl *, 32> - InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); - - // If any of our property implementations have associated getters or - // setters, produce metadata for them as well. - for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), - PropEnd = IDecl->propimpl_end(); - Prop != PropEnd; ++Prop) { - if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) - continue; - if (!(*Prop)->getPropertyIvarDecl()) - continue; - ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); - if (!PD) - continue; - if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) - if (!Getter->isDefined()) - InstanceMethods.push_back(Getter); - if (PD->isReadOnly()) - continue; - if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) - if (!Setter->isDefined()) - InstanceMethods.push_back(Setter); - } - RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), - true, "", IDecl->getName(), Result); - - // Build _objc_method_list for class's class methods if needed - RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), - false, "", IDecl->getName(), Result); - - // Protocols referenced in class declaration? - RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), - "CLASS", CDecl->getName(), Result); - - // Declaration of class/meta-class metadata - /* struct _objc_class { - struct _objc_class *isa; // or const char *root_class_name when metadata - const char *super_class_name; - char *name; - long version; - long info; - long instance_size; - struct _objc_ivar_list *ivars; - struct _objc_method_list *methods; - struct objc_cache *cache; - struct objc_protocol_list *protocols; - const char *ivar_layout; - struct _objc_class_ext *ext; - }; - */ - static bool objc_class = false; - if (!objc_class) { - Result += "\nstruct _objc_class {\n"; - Result += "\tstruct _objc_class *isa;\n"; - Result += "\tconst char *super_class_name;\n"; - Result += "\tchar *name;\n"; - Result += "\tlong version;\n"; - Result += "\tlong info;\n"; - Result += "\tlong instance_size;\n"; - Result += "\tstruct _objc_ivar_list *ivars;\n"; - Result += "\tstruct _objc_method_list *methods;\n"; - Result += "\tstruct objc_cache *cache;\n"; - Result += "\tstruct _objc_protocol_list *protocols;\n"; - Result += "\tconst char *ivar_layout;\n"; - Result += "\tstruct _objc_class_ext *ext;\n"; - Result += "};\n"; - objc_class = true; - } - - // Meta-class metadata generation. - ObjCInterfaceDecl *RootClass = 0; - ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); - while (SuperClass) { - RootClass = SuperClass; - SuperClass = SuperClass->getSuperClass(); - } - SuperClass = CDecl->getSuperClass(); - - Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; - Result += CDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " - "{\n\t(struct _objc_class *)\""; - Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString()); - Result += "\""; - - if (SuperClass) { - Result += ", \""; - Result += SuperClass->getNameAsString(); - Result += "\", \""; - Result += CDecl->getNameAsString(); - Result += "\""; - } - else { - Result += ", 0, \""; - Result += CDecl->getNameAsString(); - Result += "\""; - } - // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. - // 'info' field is initialized to CLS_META(2) for metaclass - Result += ", 0,2, sizeof(struct _objc_class), 0"; - if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { - Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; - Result += IDecl->getNameAsString(); - Result += "\n"; - } - else - Result += ", 0\n"; - if (CDecl->protocol_begin() != CDecl->protocol_end()) { - Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; - Result += CDecl->getNameAsString(); - Result += ",0,0\n"; - } - else - Result += "\t,0,0,0,0\n"; - Result += "};\n"; - - // class metadata generation. - Result += "\nstatic struct _objc_class _OBJC_CLASS_"; - Result += CDecl->getNameAsString(); - Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= " - "{\n\t&_OBJC_METACLASS_"; - Result += CDecl->getNameAsString(); - if (SuperClass) { - Result += ", \""; - Result += SuperClass->getNameAsString(); - Result += "\", \""; - Result += CDecl->getNameAsString(); - Result += "\""; - } - else { - Result += ", 0, \""; - Result += CDecl->getNameAsString(); - Result += "\""; - } - // 'info' field is initialized to CLS_CLASS(1) for class - Result += ", 0,1"; - if (!ObjCSynthesizedStructs.count(CDecl)) - Result += ",0"; - else { - // class has size. Must synthesize its size. - Result += ",sizeof(struct "; - Result += CDecl->getNameAsString(); - if (LangOpts.MicrosoftExt) - Result += "_IMPL"; - Result += ")"; - } - if (NumIvars > 0) { - Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_"; - Result += CDecl->getNameAsString(); - Result += "\n\t"; - } - else - Result += ",0"; - if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { - Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; - Result += CDecl->getNameAsString(); - Result += ", 0\n\t"; - } - else - Result += ",0,0"; - if (CDecl->protocol_begin() != CDecl->protocol_end()) { - Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; - Result += CDecl->getNameAsString(); - Result += ", 0,0\n"; - } - else - Result += ",0,0,0\n"; - Result += "};\n"; -} /// RewriteImplementations - This routine rewrites all method implementations /// and emits meta-data. @@ -4118,103 +3307,6 @@ void RewriteObjC::RewriteImplementations() { RewriteImplementationDecl(CategoryImplementation[i]); } -void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { - int ClsDefCount = ClassImplementation.size(); - int CatDefCount = CategoryImplementation.size(); - - // For each implemented class, write out all its meta data. - for (int i = 0; i < ClsDefCount; i++) - RewriteObjCClassMetaData(ClassImplementation[i], Result); - - // For each implemented category, write out all its meta data. - for (int i = 0; i < CatDefCount; i++) - RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); - - // Write objc_symtab metadata - /* - struct _objc_symtab - { - long sel_ref_cnt; - SEL *refs; - short cls_def_cnt; - short cat_def_cnt; - void *defs[cls_def_cnt + cat_def_cnt]; - }; - */ - - Result += "\nstruct _objc_symtab {\n"; - Result += "\tlong sel_ref_cnt;\n"; - Result += "\tSEL *refs;\n"; - Result += "\tshort cls_def_cnt;\n"; - Result += "\tshort cat_def_cnt;\n"; - Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n"; - Result += "};\n\n"; - - Result += "static struct _objc_symtab " - "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n"; - Result += "\t0, 0, " + utostr(ClsDefCount) - + ", " + utostr(CatDefCount) + "\n"; - for (int i = 0; i < ClsDefCount; i++) { - Result += "\t,&_OBJC_CLASS_"; - Result += ClassImplementation[i]->getNameAsString(); - Result += "\n"; - } - - for (int i = 0; i < CatDefCount; i++) { - Result += "\t,&_OBJC_CATEGORY_"; - Result += CategoryImplementation[i]->getClassInterface()->getNameAsString(); - Result += "_"; - Result += CategoryImplementation[i]->getNameAsString(); - Result += "\n"; - } - - Result += "};\n\n"; - - // Write objc_module metadata - - /* - struct _objc_module { - long version; - long size; - const char *name; - struct _objc_symtab *symtab; - } - */ - - Result += "\nstruct _objc_module {\n"; - Result += "\tlong version;\n"; - Result += "\tlong size;\n"; - Result += "\tconst char *name;\n"; - Result += "\tstruct _objc_symtab *symtab;\n"; - Result += "};\n\n"; - Result += "static struct _objc_module " - "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n"; - Result += "\t" + utostr(OBJC_ABI_VERSION) + - ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n"; - Result += "};\n\n"; - - if (LangOpts.MicrosoftExt) { - if (ProtocolExprDecls.size()) { - Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n"; - Result += "#pragma data_seg(push, \".objc_protocol$B\")\n"; - for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), - E = ProtocolExprDecls.end(); I != E; ++I) { - Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_"; - Result += (*I)->getNameAsString(); - Result += " = &_OBJC_PROTOCOL_"; - Result += (*I)->getNameAsString(); - Result += ";\n"; - } - Result += "#pragma data_seg(pop)\n\n"; - } - Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n"; - Result += "#pragma data_seg(push, \".objc_module_info$B\")\n"; - Result += "static struct _objc_module *_POINTER_OBJC_MODULES = "; - Result += "&_OBJC_MODULES;\n"; - Result += "#pragma data_seg(pop)\n\n"; - } -} - void RewriteObjC::RewriteByRefString(std::string &ResultStr, const std::string &Name, ValueDecl *VD, bool def) { @@ -4261,10 +3353,8 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, if (AI != BD->param_begin()) S += ", "; ParamStr = (*AI)->getNameAsString(); QualType QT = (*AI)->getType(); - if (convertBlockPointerToFunctionPointer(QT)) - QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); - else - QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); + (void)convertBlockPointerToFunctionPointer(QT); + QT.getAsStringInternal(ParamStr, Context->getPrintingPolicy()); S += ParamStr; } if (FT->isVariadic()) { @@ -4539,20 +3629,20 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, // Need to copy-in the inner copied-in variables not actually used in this // block. for (int j = 0; j < InnerDeclRefsCount[i]; j++) { - BlockDeclRefExpr *Exp = InnerDeclRefs[count++]; + DeclRefExpr *Exp = InnerDeclRefs[count++]; ValueDecl *VD = Exp->getDecl(); BlockDeclRefs.push_back(Exp); - if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) { + if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { BlockByCopyDeclsPtrSet.insert(VD); BlockByCopyDecls.push_back(VD); } - if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) { + if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { BlockByRefDeclsPtrSet.insert(VD); BlockByRefDecls.push_back(VD); } // imported objects in the inner blocks not used in the outer // blocks must be copied/disposed in the outer block as well. - if (Exp->isByRef() || + if (VD->hasAttr<BlocksAttr>() || VD->getType()->isObjCObjectPointerType() || VD->getType()->isBlockPointerType()) ImportedBlockDecls.insert(VD); @@ -4641,25 +3731,21 @@ void RewriteObjC::GetBlockDeclRefExprs(Stmt *S) { GetBlockDeclRefExprs(*CI); } // Handle specific things. - if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) { - // FIXME: Handle enums. - if (!isa<FunctionDecl>(CDRE->getDecl())) - BlockDeclRefs.push_back(CDRE); - } - else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) - if (HasLocalVariableExternalStorage(DRE->getDecl())) { - BlockDeclRefExpr *BDRE = - new (Context)BlockDeclRefExpr(cast<VarDecl>(DRE->getDecl()), - DRE->getType(), - VK_LValue, DRE->getLocation(), false); - BlockDeclRefs.push_back(BDRE); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { + if (DRE->refersToEnclosingLocal()) { + // FIXME: Handle enums. + if (!isa<FunctionDecl>(DRE->getDecl())) + BlockDeclRefs.push_back(DRE); + if (HasLocalVariableExternalStorage(DRE->getDecl())) + BlockDeclRefs.push_back(DRE); } + } return; } void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, - SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs, + SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs, llvm::SmallPtrSet<const DeclContext *, 8> &InnerContexts) { for (Stmt::child_range CI = S->children(); CI; ++CI) if (*CI) { @@ -4676,15 +3762,15 @@ void RewriteObjC::GetInnerBlockDeclRefExprs(Stmt *S, } // Handle specific things. - if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) { - if (!isa<FunctionDecl>(CDRE->getDecl()) && - !InnerContexts.count(CDRE->getDecl()->getDeclContext())) - InnerBlockDeclRefs.push_back(CDRE); - } - else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { - if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) - if (Var->isFunctionOrMethodVarDecl()) - ImportedLocalExternalDecls.insert(Var); + if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { + if (DRE->refersToEnclosingLocal()) { + if (!isa<FunctionDecl>(DRE->getDecl()) && + !InnerContexts.count(DRE->getDecl()->getDeclContext())) + InnerBlockDeclRefs.push_back(DRE); + if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) + if (Var->isFunctionOrMethodVarDecl()) + ImportedLocalExternalDecls.insert(Var); + } } return; @@ -4727,9 +3813,6 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(BlockExp)) { CPT = DRE->getType()->getAs<BlockPointerType>(); - } else if (const BlockDeclRefExpr *CDRE = - dyn_cast<BlockDeclRefExpr>(BlockExp)) { - CPT = CDRE->getType()->getAs<BlockPointerType>(); } else if (const MemberExpr *MExpr = dyn_cast<MemberExpr>(BlockExp)) { CPT = MExpr->getType()->getAs<BlockPointerType>(); } @@ -4753,6 +3836,9 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { return CondExpr; } else if (const ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(BlockExp)) { CPT = IRE->getType()->getAs<BlockPointerType>(); + } else if (const PseudoObjectExpr *POE + = dyn_cast<PseudoObjectExpr>(BlockExp)) { + CPT = POE->getType()->castAs<BlockPointerType>(); } else { assert(1 && "RewriteBlockClass: Bad type"); } @@ -4839,17 +3925,11 @@ Stmt *RewriteObjC::SynthesizeBlockCall(CallExpr *Exp, const Expr *BlockExp) { // i = 77; // }; //} -Stmt *RewriteObjC::RewriteBlockDeclRefExpr(Expr *DeclRefExp) { +Stmt *RewriteObjC::RewriteBlockDeclRefExpr(DeclRefExpr *DeclRefExp) { // Rewrite the byref variable into BYREFVAR->__forwarding->BYREFVAR // for each DeclRefExp where BYREFVAR is name of the variable. - ValueDecl *VD; - bool isArrow = true; - if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(DeclRefExp)) - VD = BDRE->getDecl(); - else { - VD = cast<DeclRefExpr>(DeclRefExp)->getDecl(); - isArrow = false; - } + ValueDecl *VD = DeclRefExp->getDecl(); + bool isArrow = DeclRefExp->refersToEnclosingLocal(); FieldDecl *FD = FieldDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), @@ -5343,7 +4423,7 @@ void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { if (BlockDeclRefs.size()) { // Unique all "by copy" declarations. for (unsigned i = 0; i < BlockDeclRefs.size(); i++) - if (!BlockDeclRefs[i]->isByRef()) { + if (!BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); @@ -5351,7 +4431,7 @@ void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { } // Unique all "by ref" declarations. for (unsigned i = 0; i < BlockDeclRefs.size(); i++) - if (BlockDeclRefs[i]->isByRef()) { + if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>()) { if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); @@ -5359,7 +4439,7 @@ void RewriteObjC::CollectBlockDeclRefInfo(BlockExpr *Exp) { } // Find any imported blocks...they will need special attention. for (unsigned i = 0; i < BlockDeclRefs.size(); i++) - if (BlockDeclRefs[i]->isByRef() || + if (BlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || BlockDeclRefs[i]->getType()->isObjCObjectPointerType() || BlockDeclRefs[i]->getType()->isBlockPointerType()) ImportedBlockDecls.insert(BlockDeclRefs[i]->getDecl()); @@ -5375,7 +4455,7 @@ FunctionDecl *RewriteObjC::SynthBlockInitFunctionDecl(StringRef name) { } Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, - const SmallVector<BlockDeclRefExpr *, 8> &InnerBlockDeclRefs) { + const SmallVector<DeclRefExpr *, 8> &InnerBlockDeclRefs) { const BlockDecl *block = Exp->getBlockDecl(); Blocks.push_back(Exp); @@ -5385,9 +4465,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, int countOfInnerDecls = 0; if (!InnerBlockDeclRefs.empty()) { for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) { - BlockDeclRefExpr *Exp = InnerBlockDeclRefs[i]; + DeclRefExpr *Exp = InnerBlockDeclRefs[i]; ValueDecl *VD = Exp->getDecl(); - if (!Exp->isByRef() && !BlockByCopyDeclsPtrSet.count(VD)) { + if (!VD->hasAttr<BlocksAttr>() && !BlockByCopyDeclsPtrSet.count(VD)) { // We need to save the copied-in variables in nested // blocks because it is needed at the end for some of the API generations. // See SynthesizeBlockLiterals routine. @@ -5396,7 +4476,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, BlockByCopyDeclsPtrSet.insert(VD); BlockByCopyDecls.push_back(VD); } - if (Exp->isByRef() && !BlockByRefDeclsPtrSet.count(VD)) { + if (VD->hasAttr<BlocksAttr>() && !BlockByRefDeclsPtrSet.count(VD)) { InnerDeclRefs.push_back(Exp); countOfInnerDecls++; BlockDeclRefs.push_back(Exp); BlockByRefDeclsPtrSet.insert(VD); @@ -5405,7 +4485,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, } // Find any imported blocks...they will need special attention. for (unsigned i = 0; i < InnerBlockDeclRefs.size(); i++) - if (InnerBlockDeclRefs[i]->isByRef() || + if (InnerBlockDeclRefs[i]->getDecl()->hasAttr<BlocksAttr>() || InnerBlockDeclRefs[i]->getType()->isObjCObjectPointerType() || InnerBlockDeclRefs[i]->getType()->isBlockPointerType()) ImportedBlockDecls.insert(InnerBlockDeclRefs[i]->getDecl()); @@ -5435,15 +4515,15 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, // Simulate a contructor call... FD = SynthBlockInitFunctionDecl(Tag); - DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, FType, VK_RValue, + DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, false, FType, VK_RValue, SourceLocation()); SmallVector<Expr*, 4> InitExprs; // Initialize the block function. FD = SynthBlockInitFunctionDecl(Func); - DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, - SourceLocation()); + DeclRefExpr *Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), + VK_LValue, SourceLocation()); CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg); InitExprs.push_back(castExpr); @@ -5457,7 +4537,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, Context->VoidPtrTy, 0, SC_Static, SC_None); UnaryOperator *DescRefExpr = - new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, + new (Context) UnaryOperator(new (Context) DeclRefExpr(NewVD, false, Context->VoidPtrTy, VK_LValue, SourceLocation()), @@ -5476,7 +4556,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, if (isObjCType((*I)->getType())) { // FIXME: Conform to ABI ([[obj retain] autorelease]). FD = SynthBlockInitFunctionDecl((*I)->getName()); - Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, + Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, SourceLocation()); if (HasLocalVariableExternalStorage(*I)) { QualType QT = (*I)->getType(); @@ -5486,13 +4566,13 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, } } else if (isTopLevelBlockPointerType((*I)->getType())) { FD = SynthBlockInitFunctionDecl((*I)->getName()); - Arg = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, + Arg = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, SourceLocation()); Exp = NoTypeInfoCStyleCastExpr(Context, Context->VoidPtrTy, CK_BitCast, Arg); } else { FD = SynthBlockInitFunctionDecl((*I)->getName()); - Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, + Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, SourceLocation()); if (HasLocalVariableExternalStorage(*I)) { QualType QT = (*I)->getType(); @@ -5520,7 +4600,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp, QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); FD = SynthBlockInitFunctionDecl((*I)->getName()); - Exp = new (Context) DeclRefExpr(FD, FD->getType(), VK_LValue, + Exp = new (Context) DeclRefExpr(FD, false, FD->getType(), VK_LValue, SourceLocation()); bool isNestedCapturedVar = false; if (block) @@ -5580,26 +4660,6 @@ bool RewriteObjC::IsDeclStmtInForeachHeader(DeclStmt *DS) { // Function Body / Expression rewriting //===----------------------------------------------------------------------===// -// This is run as a first "pass" prior to RewriteFunctionBodyOrGlobalInitializer(). -// The allows the main rewrite loop to associate all ObjCPropertyRefExprs with -// their respective BinaryOperator. Without this knowledge, we'd need to rewrite -// the ObjCPropertyRefExpr twice (once as a getter, and later as a setter). -// Since the rewriter isn't capable of rewriting rewritten code, it's important -// we get this right. -void RewriteObjC::CollectPropertySetters(Stmt *S) { - // Perform a bottom up traversal of all children. - for (Stmt::child_range CI = S->children(); CI; ++CI) - if (*CI) - CollectPropertySetters(*CI); - - if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { - if (BinOp->isAssignmentOp()) { - if (isa<ObjCPropertyRefExpr>(BinOp->getLHS())) - PropSetters[BinOp->getLHS()] = BinOp; - } - } -} - Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (isa<SwitchStmt>(S) || isa<WhileStmt>(S) || isa<DoStmt>(S) || isa<ForStmt>(S)) @@ -5609,50 +4669,32 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { ObjCBcLabelNo.push_back(++BcLabelCount); } + // Pseudo-object operations and ivar references need special + // treatment because we're going to recursively rewrite them. + if (PseudoObjectExpr *PseudoOp = dyn_cast<PseudoObjectExpr>(S)) { + if (isa<BinaryOperator>(PseudoOp->getSyntacticForm())) { + return RewritePropertyOrImplicitSetter(PseudoOp); + } else { + return RewritePropertyOrImplicitGetter(PseudoOp); + } + } else if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { + return RewriteObjCIvarRefExpr(IvarRefExpr); + } + SourceRange OrigStmtRange = S->getSourceRange(); // Perform a bottom up rewrite of all children. for (Stmt::child_range CI = S->children(); CI; ++CI) if (*CI) { - Stmt *newStmt; - Stmt *ChildStmt = (*CI); - if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(ChildStmt)) { - Expr *OldBase = IvarRefExpr->getBase(); - bool replaced = false; - newStmt = RewriteObjCNestedIvarRefExpr(ChildStmt, replaced); - if (replaced) { - if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt)) - ReplaceStmt(OldBase, IRE->getBase()); - else - ReplaceStmt(ChildStmt, newStmt); - } - } - else - newStmt = RewriteFunctionBodyOrGlobalInitializer(ChildStmt); + Stmt *childStmt = (*CI); + Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(childStmt); if (newStmt) { - if (Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(ChildStmt)) - if (PropSetters[PropOrImplicitRefExpr] == S) { - S = newStmt; - newStmt = 0; - } - if (newStmt) - *CI = newStmt; + *CI = newStmt; } - // If dealing with an assignment with LHS being a property reference - // expression, the entire assignment tree is rewritten into a property - // setter messaging. This involvs the RHS too. Do not attempt to rewrite - // RHS again. - if (Expr *Exp = dyn_cast<Expr>(ChildStmt)) - if (isa<ObjCPropertyRefExpr>(Exp)) { - if (PropSetters[Exp]) { - ++CI; - continue; - } - } } if (BlockExpr *BE = dyn_cast<BlockExpr>(S)) { - SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs; + SmallVector<DeclRefExpr *, 8> InnerBlockDeclRefs; llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts; InnerContexts.insert(BE->getBlockDecl()); ImportedLocalExternalDecls.clear(); @@ -5661,7 +4703,6 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { // Rewrite the block body in place. Stmt *SaveCurrentBody = CurrentBody; CurrentBody = BE->getBody(); - CollectPropertySetters(CurrentBody); PropParentMap = 0; // block literal on rhs of a property-dot-sytax assignment // must be replaced by its synthesize ast so getRewrittenText @@ -5689,67 +4730,6 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) return RewriteAtEncode(AtEncode); - if (isa<ObjCPropertyRefExpr>(S)) { - Expr *PropOrImplicitRefExpr = dyn_cast<Expr>(S); - assert(PropOrImplicitRefExpr && "Property or implicit setter/getter is null"); - - BinaryOperator *BinOp = PropSetters[PropOrImplicitRefExpr]; - if (BinOp) { - // Because the rewriter doesn't allow us to rewrite rewritten code, - // we need to rewrite the right hand side prior to rewriting the setter. - DisableReplaceStmt = true; - // Save the source range. Even if we disable the replacement, the - // rewritten node will have been inserted into the tree. If the synthesized - // node is at the 'end', the rewriter will fail. Consider this: - // self.errorHandler = handler ? handler : - // ^(NSURL *errorURL, NSError *error) { return (BOOL)1; }; - SourceRange SrcRange = BinOp->getSourceRange(); - Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(BinOp->getRHS()); - // Need to rewrite the ivar access expression if need be. - if (isa<ObjCIvarRefExpr>(newStmt)) { - bool replaced = false; - newStmt = RewriteObjCNestedIvarRefExpr(newStmt, replaced); - } - - DisableReplaceStmt = false; - // - // Unlike the main iterator, we explicily avoid changing 'BinOp'. If - // we changed the RHS of BinOp, the rewriter would fail (since it needs - // to see the original expression). Consider this example: - // - // Foo *obj1, *obj2; - // - // obj1.i = [obj2 rrrr]; - // - // 'BinOp' for the previous expression looks like: - // - // (BinaryOperator 0x231ccf0 'int' '=' - // (ObjCPropertyRefExpr 0x231cc70 'int' Kind=PropertyRef Property="i" - // (DeclRefExpr 0x231cc50 'Foo *' Var='obj1' 0x231cbb0)) - // (ObjCMessageExpr 0x231ccb0 'int' selector=rrrr - // (DeclRefExpr 0x231cc90 'Foo *' Var='obj2' 0x231cbe0))) - // - // 'newStmt' represents the rewritten message expression. For example: - // - // (CallExpr 0x231d300 'id':'struct objc_object *' - // (ParenExpr 0x231d2e0 'int (*)(id, SEL)' - // (CStyleCastExpr 0x231d2c0 'int (*)(id, SEL)' - // (CStyleCastExpr 0x231d220 'void *' - // (DeclRefExpr 0x231d200 'id (id, SEL, ...)' FunctionDecl='objc_msgSend' 0x231cdc0)))) - // - // Note that 'newStmt' is passed to RewritePropertyOrImplicitSetter so that it - // can be used as the setter argument. ReplaceStmt() will still 'see' - // the original RHS (since we haven't altered BinOp). - // - // This implies the Rewrite* routines can no longer delete the original - // node. As a result, we now leak the original AST nodes. - // - return RewritePropertyOrImplicitSetter(BinOp, dyn_cast<Expr>(newStmt), SrcRange); - } else { - return RewritePropertyOrImplicitGetter(PropOrImplicitRefExpr); - } - } - if (ObjCSelectorExpr *AtSelector = dyn_cast<ObjCSelectorExpr>(S)) return RewriteAtSelector(AtSelector); @@ -5859,10 +4839,6 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { Stmts.pop_back(); } // Handle blocks rewriting. - if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) { - if (BDRE->isByRef()) - return RewriteBlockDeclRefExpr(BDRE); - } if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) { ValueDecl *VD = DRE->getDecl(); if (VD->hasAttr<BlocksAttr>()) @@ -5917,108 +4893,124 @@ void RewriteObjC::RewriteRecordBody(RecordDecl *RD) { /// HandleDeclInMainFile - This is called for each top-level decl defined in the /// main file of the input. void RewriteObjC::HandleDeclInMainFile(Decl *D) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - if (FD->isOverloadedOperator()) - return; + switch (D->getKind()) { + case Decl::Function: { + FunctionDecl *FD = cast<FunctionDecl>(D); + if (FD->isOverloadedOperator()) + return; - // Since function prototypes don't have ParmDecl's, we check the function - // prototype. This enables us to rewrite function declarations and - // definitions using the same code. - RewriteBlocksInFunctionProtoType(FD->getType(), FD); - - // FIXME: If this should support Obj-C++, support CXXTryStmt - if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { - CurFunctionDef = FD; - CurFunctionDeclToDeclareForBlock = FD; - CollectPropertySetters(Body); - CurrentBody = Body; - Body = - cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); - FD->setBody(Body); - CurrentBody = 0; - if (PropParentMap) { - delete PropParentMap; - PropParentMap = 0; + // Since function prototypes don't have ParmDecl's, we check the function + // prototype. This enables us to rewrite function declarations and + // definitions using the same code. + RewriteBlocksInFunctionProtoType(FD->getType(), FD); + + if (!FD->isThisDeclarationADefinition()) + break; + + // FIXME: If this should support Obj-C++, support CXXTryStmt + if (CompoundStmt *Body = dyn_cast_or_null<CompoundStmt>(FD->getBody())) { + CurFunctionDef = FD; + CurFunctionDeclToDeclareForBlock = FD; + CurrentBody = Body; + Body = + cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); + FD->setBody(Body); + CurrentBody = 0; + if (PropParentMap) { + delete PropParentMap; + PropParentMap = 0; + } + // This synthesizes and inserts the block "impl" struct, invoke function, + // and any copy/dispose helper functions. + InsertBlockLiteralsWithinFunction(FD); + CurFunctionDef = 0; + CurFunctionDeclToDeclareForBlock = 0; } - // This synthesizes and inserts the block "impl" struct, invoke function, - // and any copy/dispose helper functions. - InsertBlockLiteralsWithinFunction(FD); - CurFunctionDef = 0; - CurFunctionDeclToDeclareForBlock = 0; + break; } - return; - } - if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { - if (CompoundStmt *Body = MD->getCompoundBody()) { - CurMethodDef = MD; - CollectPropertySetters(Body); - CurrentBody = Body; - Body = - cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); - MD->setBody(Body); - CurrentBody = 0; - if (PropParentMap) { - delete PropParentMap; - PropParentMap = 0; + case Decl::ObjCMethod: { + ObjCMethodDecl *MD = cast<ObjCMethodDecl>(D); + if (CompoundStmt *Body = MD->getCompoundBody()) { + CurMethodDef = MD; + CurrentBody = Body; + Body = + cast_or_null<CompoundStmt>(RewriteFunctionBodyOrGlobalInitializer(Body)); + MD->setBody(Body); + CurrentBody = 0; + if (PropParentMap) { + delete PropParentMap; + PropParentMap = 0; + } + InsertBlockLiteralsWithinMethod(MD); + CurMethodDef = 0; } - InsertBlockLiteralsWithinMethod(MD); - CurMethodDef = 0; + break; } - } - if (ObjCImplementationDecl *CI = dyn_cast<ObjCImplementationDecl>(D)) - ClassImplementation.push_back(CI); - else if (ObjCCategoryImplDecl *CI = dyn_cast<ObjCCategoryImplDecl>(D)) - CategoryImplementation.push_back(CI); - else if (isa<ObjCClassDecl>(D)) - llvm_unreachable("RewriteObjC::HandleDeclInMainFile - ObjCClassDecl"); - else if (VarDecl *VD = dyn_cast<VarDecl>(D)) { - RewriteObjCQualifiedInterfaceTypes(VD); - if (isTopLevelBlockPointerType(VD->getType())) - RewriteBlockPointerDecl(VD); - else if (VD->getType()->isFunctionPointerType()) { - CheckFunctionPointerDecl(VD->getType(), VD); + case Decl::ObjCImplementation: { + ObjCImplementationDecl *CI = cast<ObjCImplementationDecl>(D); + ClassImplementation.push_back(CI); + break; + } + case Decl::ObjCCategoryImpl: { + ObjCCategoryImplDecl *CI = cast<ObjCCategoryImplDecl>(D); + CategoryImplementation.push_back(CI); + break; + } + case Decl::Var: { + VarDecl *VD = cast<VarDecl>(D); + RewriteObjCQualifiedInterfaceTypes(VD); + if (isTopLevelBlockPointerType(VD->getType())) + RewriteBlockPointerDecl(VD); + else if (VD->getType()->isFunctionPointerType()) { + CheckFunctionPointerDecl(VD->getType(), VD); + if (VD->getInit()) { + if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { + RewriteCastExpr(CE); + } + } + } else if (VD->getType()->isRecordType()) { + RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl(); + if (RD->isCompleteDefinition()) + RewriteRecordBody(RD); + } if (VD->getInit()) { + GlobalVarDecl = VD; + CurrentBody = VD->getInit(); + RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); + CurrentBody = 0; + if (PropParentMap) { + delete PropParentMap; + PropParentMap = 0; + } + SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), VD->getName()); + GlobalVarDecl = 0; + + // This is needed for blocks. if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { - RewriteCastExpr(CE); + RewriteCastExpr(CE); } } - } else if (VD->getType()->isRecordType()) { - RecordDecl *RD = VD->getType()->getAs<RecordType>()->getDecl(); - if (RD->isCompleteDefinition()) - RewriteRecordBody(RD); + break; } - if (VD->getInit()) { - GlobalVarDecl = VD; - CollectPropertySetters(VD->getInit()); - CurrentBody = VD->getInit(); - RewriteFunctionBodyOrGlobalInitializer(VD->getInit()); - CurrentBody = 0; - if (PropParentMap) { - delete PropParentMap; - PropParentMap = 0; - } - SynthesizeBlockLiterals(VD->getTypeSpecStartLoc(), - VD->getName()); - GlobalVarDecl = 0; - - // This is needed for blocks. - if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(VD->getInit())) { - RewriteCastExpr(CE); + case Decl::TypeAlias: + case Decl::Typedef: { + if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { + if (isTopLevelBlockPointerType(TD->getUnderlyingType())) + RewriteBlockPointerDecl(TD); + else if (TD->getUnderlyingType()->isFunctionPointerType()) + CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); } + break; } - return; - } - if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { - if (isTopLevelBlockPointerType(TD->getUnderlyingType())) - RewriteBlockPointerDecl(TD); - else if (TD->getUnderlyingType()->isFunctionPointerType()) - CheckFunctionPointerDecl(TD->getUnderlyingType(), TD); - return; - } - if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { - if (RD->isCompleteDefinition()) - RewriteRecordBody(RD); - return; + case Decl::CXXRecord: + case Decl::Record: { + RecordDecl *RD = cast<RecordDecl>(D); + if (RD->isCompleteDefinition()) + RewriteRecordBody(RD); + break; + } + default: + break; } // Nothing yet. } @@ -6053,9 +5045,974 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) { ProtocolExprDecls.size()) { // Rewrite Objective-c meta data* std::string ResultStr; - SynthesizeMetaDataIntoBuffer(ResultStr); + RewriteMetaDataIntoBuffer(ResultStr); // Emit metadata. *OutFile << ResultStr; } OutFile->flush(); } + +void RewriteObjCFragileABI::Initialize(ASTContext &context) { + InitializeCommon(context); + + // declaring objc_selector outside the parameter list removes a silly + // scope related warning... + if (IsHeader) + Preamble = "#pragma once\n"; + Preamble += "struct objc_selector; struct objc_class;\n"; + Preamble += "struct __rw_objc_super { struct objc_object *object; "; + Preamble += "struct objc_object *superClass; "; + if (LangOpts.MicrosoftExt) { + // Add a constructor for creating temporary objects. + Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) " + ": "; + Preamble += "object(o), superClass(s) {} "; + } + Preamble += "};\n"; + Preamble += "#ifndef _REWRITER_typedef_Protocol\n"; + Preamble += "typedef struct objc_object Protocol;\n"; + Preamble += "#define _REWRITER_typedef_Protocol\n"; + Preamble += "#endif\n"; + if (LangOpts.MicrosoftExt) { + Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n"; + Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n"; + } else + Preamble += "#define __OBJC_RW_DLLIMPORT extern\n"; + Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend"; + Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; + Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper"; + Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; + Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSend_stret"; + Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; + Preamble += "__OBJC_RW_DLLIMPORT struct objc_object* objc_msgSendSuper_stret"; + Preamble += "(struct objc_super *, struct objc_selector *, ...);\n"; + Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret"; + Preamble += "(struct objc_object *, struct objc_selector *, ...);\n"; + Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass"; + Preamble += "(const char *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT struct objc_class *class_getSuperclass"; + Preamble += "(struct objc_class *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass"; + Preamble += "(const char *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match"; + Preamble += "(struct objc_class *, struct objc_object *);\n"; + // @synchronized hooks. + Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n"; + Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n"; + Preamble += "#ifndef __FASTENUMERATIONSTATE\n"; + Preamble += "struct __objcFastEnumerationState {\n\t"; + Preamble += "unsigned long state;\n\t"; + Preamble += "void **itemsPtr;\n\t"; + Preamble += "unsigned long *mutationsPtr;\n\t"; + Preamble += "unsigned long extra[5];\n};\n"; + Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n"; + Preamble += "#define __FASTENUMERATIONSTATE\n"; + Preamble += "#endif\n"; + Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n"; + Preamble += "struct __NSConstantStringImpl {\n"; + Preamble += " int *isa;\n"; + Preamble += " int flags;\n"; + Preamble += " char *str;\n"; + Preamble += " long length;\n"; + Preamble += "};\n"; + Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n"; + Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n"; + Preamble += "#else\n"; + Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n"; + Preamble += "#endif\n"; + Preamble += "#define __NSCONSTANTSTRINGIMPL\n"; + Preamble += "#endif\n"; + // Blocks preamble. + Preamble += "#ifndef BLOCK_IMPL\n"; + Preamble += "#define BLOCK_IMPL\n"; + Preamble += "struct __block_impl {\n"; + Preamble += " void *isa;\n"; + Preamble += " int Flags;\n"; + Preamble += " int Reserved;\n"; + Preamble += " void *FuncPtr;\n"; + Preamble += "};\n"; + Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n"; + Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n"; + Preamble += "extern \"C\" __declspec(dllexport) " + "void _Block_object_assign(void *, const void *, const int);\n"; + Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n"; + Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n"; + Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n"; + Preamble += "#else\n"; + Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n"; + Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n"; + Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n"; + Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n"; + Preamble += "#endif\n"; + Preamble += "#endif\n"; + if (LangOpts.MicrosoftExt) { + Preamble += "#undef __OBJC_RW_DLLIMPORT\n"; + Preamble += "#undef __OBJC_RW_STATICIMPORT\n"; + Preamble += "#ifndef KEEP_ATTRIBUTES\n"; // We use this for clang tests. + Preamble += "#define __attribute__(X)\n"; + Preamble += "#endif\n"; + Preamble += "#define __weak\n"; + } + else { + Preamble += "#define __block\n"; + Preamble += "#define __weak\n"; + } + // NOTE! Windows uses LLP64 for 64bit mode. So, cast pointer to long long + // as this avoids warning in any 64bit/32bit compilation model. + Preamble += "\n#define __OFFSETOFIVAR__(TYPE, MEMBER) ((long long) &((TYPE *)0)->MEMBER)\n"; +} + +/// RewriteIvarOffsetComputation - This rutine synthesizes computation of +/// ivar offset. +void RewriteObjCFragileABI::RewriteIvarOffsetComputation(ObjCIvarDecl *ivar, + std::string &Result) { + if (ivar->isBitField()) { + // FIXME: The hack below doesn't work for bitfields. For now, we simply + // place all bitfields at offset 0. + Result += "0"; + } else { + Result += "__OFFSETOFIVAR__(struct "; + Result += ivar->getContainingInterface()->getNameAsString(); + if (LangOpts.MicrosoftExt) + Result += "_IMPL"; + Result += ", "; + Result += ivar->getNameAsString(); + Result += ")"; + } +} + +/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. +void RewriteObjCFragileABI::RewriteObjCProtocolMetaData( + ObjCProtocolDecl *PDecl, StringRef prefix, + StringRef ClassName, std::string &Result) { + static bool objc_protocol_methods = false; + + // Output struct protocol_methods holder of method selector and type. + if (!objc_protocol_methods && PDecl->hasDefinition()) { + /* struct protocol_methods { + SEL _cmd; + char *method_types; + } + */ + Result += "\nstruct _protocol_methods {\n"; + Result += "\tstruct objc_selector *_cmd;\n"; + Result += "\tchar *method_types;\n"; + Result += "};\n"; + + objc_protocol_methods = true; + } + // Do not synthesize the protocol more than once. + if (ObjCSynthesizedProtocols.count(PDecl->getCanonicalDecl())) + return; + + if (ObjCProtocolDecl *Def = PDecl->getDefinition()) + PDecl = Def; + + if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { + unsigned NumMethods = std::distance(PDecl->instmeth_begin(), + PDecl->instmeth_end()); + /* struct _objc_protocol_method_list { + int protocol_method_count; + struct protocol_methods protocols[]; + } + */ + Result += "\nstatic struct {\n"; + Result += "\tint protocol_method_count;\n"; + Result += "\tstruct _protocol_methods protocol_methods["; + Result += utostr(NumMethods); + Result += "];\n} _OBJC_PROTOCOL_INSTANCE_METHODS_"; + Result += PDecl->getNameAsString(); + Result += " __attribute__ ((used, section (\"__OBJC, __cat_inst_meth\")))= " + "{\n\t" + utostr(NumMethods) + "\n"; + + // Output instance methods declared in this protocol. + for (ObjCProtocolDecl::instmeth_iterator + I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); + I != E; ++I) { + if (I == PDecl->instmeth_begin()) + Result += "\t ,{{(struct objc_selector *)\""; + else + Result += "\t ,{(struct objc_selector *)\""; + Result += (*I)->getSelector().getAsString(); + std::string MethodTypeString; + Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); + Result += "\", \""; + Result += MethodTypeString; + Result += "\"}\n"; + } + Result += "\t }\n};\n"; + } + + // Output class methods declared in this protocol. + unsigned NumMethods = std::distance(PDecl->classmeth_begin(), + PDecl->classmeth_end()); + if (NumMethods > 0) { + /* struct _objc_protocol_method_list { + int protocol_method_count; + struct protocol_methods protocols[]; + } + */ + Result += "\nstatic struct {\n"; + Result += "\tint protocol_method_count;\n"; + Result += "\tstruct _protocol_methods protocol_methods["; + Result += utostr(NumMethods); + Result += "];\n} _OBJC_PROTOCOL_CLASS_METHODS_"; + Result += PDecl->getNameAsString(); + Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " + "{\n\t"; + Result += utostr(NumMethods); + Result += "\n"; + + // Output instance methods declared in this protocol. + for (ObjCProtocolDecl::classmeth_iterator + I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); + I != E; ++I) { + if (I == PDecl->classmeth_begin()) + Result += "\t ,{{(struct objc_selector *)\""; + else + Result += "\t ,{(struct objc_selector *)\""; + Result += (*I)->getSelector().getAsString(); + std::string MethodTypeString; + Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); + Result += "\", \""; + Result += MethodTypeString; + Result += "\"}\n"; + } + Result += "\t }\n};\n"; + } + + // Output: + /* struct _objc_protocol { + // Objective-C 1.0 extensions + struct _objc_protocol_extension *isa; + char *protocol_name; + struct _objc_protocol **protocol_list; + struct _objc_protocol_method_list *instance_methods; + struct _objc_protocol_method_list *class_methods; + }; + */ + static bool objc_protocol = false; + if (!objc_protocol) { + Result += "\nstruct _objc_protocol {\n"; + Result += "\tstruct _objc_protocol_extension *isa;\n"; + Result += "\tchar *protocol_name;\n"; + Result += "\tstruct _objc_protocol **protocol_list;\n"; + Result += "\tstruct _objc_protocol_method_list *instance_methods;\n"; + Result += "\tstruct _objc_protocol_method_list *class_methods;\n"; + Result += "};\n"; + + objc_protocol = true; + } + + Result += "\nstatic struct _objc_protocol _OBJC_PROTOCOL_"; + Result += PDecl->getNameAsString(); + Result += " __attribute__ ((used, section (\"__OBJC, __protocol\")))= " + "{\n\t0, \""; + Result += PDecl->getNameAsString(); + Result += "\", 0, "; + if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { + Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; + Result += PDecl->getNameAsString(); + Result += ", "; + } + else + Result += "0, "; + if (PDecl->classmeth_begin() != PDecl->classmeth_end()) { + Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; + Result += PDecl->getNameAsString(); + Result += "\n"; + } + else + Result += "0\n"; + Result += "};\n"; + + // Mark this protocol as having been generated. + if (!ObjCSynthesizedProtocols.insert(PDecl->getCanonicalDecl())) + llvm_unreachable("protocol already synthesized"); + +} + +void RewriteObjCFragileABI::RewriteObjCProtocolListMetaData( + const ObjCList<ObjCProtocolDecl> &Protocols, + StringRef prefix, StringRef ClassName, + std::string &Result) { + if (Protocols.empty()) return; + + for (unsigned i = 0; i != Protocols.size(); i++) + RewriteObjCProtocolMetaData(Protocols[i], prefix, ClassName, Result); + + // Output the top lovel protocol meta-data for the class. + /* struct _objc_protocol_list { + struct _objc_protocol_list *next; + int protocol_count; + struct _objc_protocol *class_protocols[]; + } + */ + Result += "\nstatic struct {\n"; + Result += "\tstruct _objc_protocol_list *next;\n"; + Result += "\tint protocol_count;\n"; + Result += "\tstruct _objc_protocol *class_protocols["; + Result += utostr(Protocols.size()); + Result += "];\n} _OBJC_"; + Result += prefix; + Result += "_PROTOCOLS_"; + Result += ClassName; + Result += " __attribute__ ((used, section (\"__OBJC, __cat_cls_meth\")))= " + "{\n\t0, "; + Result += utostr(Protocols.size()); + Result += "\n"; + + Result += "\t,{&_OBJC_PROTOCOL_"; + Result += Protocols[0]->getNameAsString(); + Result += " \n"; + + for (unsigned i = 1; i != Protocols.size(); i++) { + Result += "\t ,&_OBJC_PROTOCOL_"; + Result += Protocols[i]->getNameAsString(); + Result += "\n"; + } + Result += "\t }\n};\n"; +} + +void RewriteObjCFragileABI::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, + std::string &Result) { + ObjCInterfaceDecl *CDecl = IDecl->getClassInterface(); + + // Explicitly declared @interface's are already synthesized. + if (CDecl->isImplicitInterfaceDecl()) { + // FIXME: Implementation of a class with no @interface (legacy) does not + // produce correct synthesis as yet. + RewriteObjCInternalStruct(CDecl, Result); + } + + // Build _objc_ivar_list metadata for classes ivars if needed + unsigned NumIvars = !IDecl->ivar_empty() + ? IDecl->ivar_size() + : (CDecl ? CDecl->ivar_size() : 0); + if (NumIvars > 0) { + static bool objc_ivar = false; + if (!objc_ivar) { + /* struct _objc_ivar { + char *ivar_name; + char *ivar_type; + int ivar_offset; + }; + */ + Result += "\nstruct _objc_ivar {\n"; + Result += "\tchar *ivar_name;\n"; + Result += "\tchar *ivar_type;\n"; + Result += "\tint ivar_offset;\n"; + Result += "};\n"; + + objc_ivar = true; + } + + /* struct { + int ivar_count; + struct _objc_ivar ivar_list[nIvars]; + }; + */ + Result += "\nstatic struct {\n"; + Result += "\tint ivar_count;\n"; + Result += "\tstruct _objc_ivar ivar_list["; + Result += utostr(NumIvars); + Result += "];\n} _OBJC_INSTANCE_VARIABLES_"; + Result += IDecl->getNameAsString(); + Result += " __attribute__ ((used, section (\"__OBJC, __instance_vars\")))= " + "{\n\t"; + Result += utostr(NumIvars); + Result += "\n"; + + ObjCInterfaceDecl::ivar_iterator IVI, IVE; + SmallVector<ObjCIvarDecl *, 8> IVars; + if (!IDecl->ivar_empty()) { + for (ObjCInterfaceDecl::ivar_iterator + IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); + IV != IVEnd; ++IV) + IVars.push_back(*IV); + IVI = IDecl->ivar_begin(); + IVE = IDecl->ivar_end(); + } else { + IVI = CDecl->ivar_begin(); + IVE = CDecl->ivar_end(); + } + Result += "\t,{{\""; + Result += (*IVI)->getNameAsString(); + Result += "\", \""; + std::string TmpString, StrEncoding; + Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); + QuoteDoublequotes(TmpString, StrEncoding); + Result += StrEncoding; + Result += "\", "; + RewriteIvarOffsetComputation(*IVI, Result); + Result += "}\n"; + for (++IVI; IVI != IVE; ++IVI) { + Result += "\t ,{\""; + Result += (*IVI)->getNameAsString(); + Result += "\", \""; + std::string TmpString, StrEncoding; + Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); + QuoteDoublequotes(TmpString, StrEncoding); + Result += StrEncoding; + Result += "\", "; + RewriteIvarOffsetComputation((*IVI), Result); + Result += "}\n"; + } + + Result += "\t }\n};\n"; + } + + // Build _objc_method_list for class's instance methods if needed + SmallVector<ObjCMethodDecl *, 32> + InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); + + // If any of our property implementations have associated getters or + // setters, produce metadata for them as well. + for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), + PropEnd = IDecl->propimpl_end(); + Prop != PropEnd; ++Prop) { + if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + continue; + if (!(*Prop)->getPropertyIvarDecl()) + continue; + ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); + if (!PD) + continue; + if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) + if (!Getter->isDefined()) + InstanceMethods.push_back(Getter); + if (PD->isReadOnly()) + continue; + if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) + if (!Setter->isDefined()) + InstanceMethods.push_back(Setter); + } + RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), + true, "", IDecl->getName(), Result); + + // Build _objc_method_list for class's class methods if needed + RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), + false, "", IDecl->getName(), Result); + + // Protocols referenced in class declaration? + RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), + "CLASS", CDecl->getName(), Result); + + // Declaration of class/meta-class metadata + /* struct _objc_class { + struct _objc_class *isa; // or const char *root_class_name when metadata + const char *super_class_name; + char *name; + long version; + long info; + long instance_size; + struct _objc_ivar_list *ivars; + struct _objc_method_list *methods; + struct objc_cache *cache; + struct objc_protocol_list *protocols; + const char *ivar_layout; + struct _objc_class_ext *ext; + }; + */ + static bool objc_class = false; + if (!objc_class) { + Result += "\nstruct _objc_class {\n"; + Result += "\tstruct _objc_class *isa;\n"; + Result += "\tconst char *super_class_name;\n"; + Result += "\tchar *name;\n"; + Result += "\tlong version;\n"; + Result += "\tlong info;\n"; + Result += "\tlong instance_size;\n"; + Result += "\tstruct _objc_ivar_list *ivars;\n"; + Result += "\tstruct _objc_method_list *methods;\n"; + Result += "\tstruct objc_cache *cache;\n"; + Result += "\tstruct _objc_protocol_list *protocols;\n"; + Result += "\tconst char *ivar_layout;\n"; + Result += "\tstruct _objc_class_ext *ext;\n"; + Result += "};\n"; + objc_class = true; + } + + // Meta-class metadata generation. + ObjCInterfaceDecl *RootClass = 0; + ObjCInterfaceDecl *SuperClass = CDecl->getSuperClass(); + while (SuperClass) { + RootClass = SuperClass; + SuperClass = SuperClass->getSuperClass(); + } + SuperClass = CDecl->getSuperClass(); + + Result += "\nstatic struct _objc_class _OBJC_METACLASS_"; + Result += CDecl->getNameAsString(); + Result += " __attribute__ ((used, section (\"__OBJC, __meta_class\")))= " + "{\n\t(struct _objc_class *)\""; + Result += (RootClass ? RootClass->getNameAsString() : CDecl->getNameAsString()); + Result += "\""; + + if (SuperClass) { + Result += ", \""; + Result += SuperClass->getNameAsString(); + Result += "\", \""; + Result += CDecl->getNameAsString(); + Result += "\""; + } + else { + Result += ", 0, \""; + Result += CDecl->getNameAsString(); + Result += "\""; + } + // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. + // 'info' field is initialized to CLS_META(2) for metaclass + Result += ", 0,2, sizeof(struct _objc_class), 0"; + if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { + Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; + Result += IDecl->getNameAsString(); + Result += "\n"; + } + else + Result += ", 0\n"; + if (CDecl->protocol_begin() != CDecl->protocol_end()) { + Result += "\t,0, (struct _objc_protocol_list *)&_OBJC_CLASS_PROTOCOLS_"; + Result += CDecl->getNameAsString(); + Result += ",0,0\n"; + } + else + Result += "\t,0,0,0,0\n"; + Result += "};\n"; + + // class metadata generation. + Result += "\nstatic struct _objc_class _OBJC_CLASS_"; + Result += CDecl->getNameAsString(); + Result += " __attribute__ ((used, section (\"__OBJC, __class\")))= " + "{\n\t&_OBJC_METACLASS_"; + Result += CDecl->getNameAsString(); + if (SuperClass) { + Result += ", \""; + Result += SuperClass->getNameAsString(); + Result += "\", \""; + Result += CDecl->getNameAsString(); + Result += "\""; + } + else { + Result += ", 0, \""; + Result += CDecl->getNameAsString(); + Result += "\""; + } + // 'info' field is initialized to CLS_CLASS(1) for class + Result += ", 0,1"; + if (!ObjCSynthesizedStructs.count(CDecl)) + Result += ",0"; + else { + // class has size. Must synthesize its size. + Result += ",sizeof(struct "; + Result += CDecl->getNameAsString(); + if (LangOpts.MicrosoftExt) + Result += "_IMPL"; + Result += ")"; + } + if (NumIvars > 0) { + Result += ", (struct _objc_ivar_list *)&_OBJC_INSTANCE_VARIABLES_"; + Result += CDecl->getNameAsString(); + Result += "\n\t"; + } + else + Result += ",0"; + if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { + Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; + Result += CDecl->getNameAsString(); + Result += ", 0\n\t"; + } + else + Result += ",0,0"; + if (CDecl->protocol_begin() != CDecl->protocol_end()) { + Result += ", (struct _objc_protocol_list*)&_OBJC_CLASS_PROTOCOLS_"; + Result += CDecl->getNameAsString(); + Result += ", 0,0\n"; + } + else + Result += ",0,0,0\n"; + Result += "};\n"; +} + +void RewriteObjCFragileABI::RewriteMetaDataIntoBuffer(std::string &Result) { + int ClsDefCount = ClassImplementation.size(); + int CatDefCount = CategoryImplementation.size(); + + // For each implemented class, write out all its meta data. + for (int i = 0; i < ClsDefCount; i++) + RewriteObjCClassMetaData(ClassImplementation[i], Result); + + // For each implemented category, write out all its meta data. + for (int i = 0; i < CatDefCount; i++) + RewriteObjCCategoryImplDecl(CategoryImplementation[i], Result); + + // Write objc_symtab metadata + /* + struct _objc_symtab + { + long sel_ref_cnt; + SEL *refs; + short cls_def_cnt; + short cat_def_cnt; + void *defs[cls_def_cnt + cat_def_cnt]; + }; + */ + + Result += "\nstruct _objc_symtab {\n"; + Result += "\tlong sel_ref_cnt;\n"; + Result += "\tSEL *refs;\n"; + Result += "\tshort cls_def_cnt;\n"; + Result += "\tshort cat_def_cnt;\n"; + Result += "\tvoid *defs[" + utostr(ClsDefCount + CatDefCount)+ "];\n"; + Result += "};\n\n"; + + Result += "static struct _objc_symtab " + "_OBJC_SYMBOLS __attribute__((used, section (\"__OBJC, __symbols\")))= {\n"; + Result += "\t0, 0, " + utostr(ClsDefCount) + + ", " + utostr(CatDefCount) + "\n"; + for (int i = 0; i < ClsDefCount; i++) { + Result += "\t,&_OBJC_CLASS_"; + Result += ClassImplementation[i]->getNameAsString(); + Result += "\n"; + } + + for (int i = 0; i < CatDefCount; i++) { + Result += "\t,&_OBJC_CATEGORY_"; + Result += CategoryImplementation[i]->getClassInterface()->getNameAsString(); + Result += "_"; + Result += CategoryImplementation[i]->getNameAsString(); + Result += "\n"; + } + + Result += "};\n\n"; + + // Write objc_module metadata + + /* + struct _objc_module { + long version; + long size; + const char *name; + struct _objc_symtab *symtab; + } + */ + + Result += "\nstruct _objc_module {\n"; + Result += "\tlong version;\n"; + Result += "\tlong size;\n"; + Result += "\tconst char *name;\n"; + Result += "\tstruct _objc_symtab *symtab;\n"; + Result += "};\n\n"; + Result += "static struct _objc_module " + "_OBJC_MODULES __attribute__ ((used, section (\"__OBJC, __module_info\")))= {\n"; + Result += "\t" + utostr(OBJC_ABI_VERSION) + + ", sizeof(struct _objc_module), \"\", &_OBJC_SYMBOLS\n"; + Result += "};\n\n"; + + if (LangOpts.MicrosoftExt) { + if (ProtocolExprDecls.size()) { + Result += "#pragma section(\".objc_protocol$B\",long,read,write)\n"; + Result += "#pragma data_seg(push, \".objc_protocol$B\")\n"; + for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), + E = ProtocolExprDecls.end(); I != E; ++I) { + Result += "static struct _objc_protocol *_POINTER_OBJC_PROTOCOL_"; + Result += (*I)->getNameAsString(); + Result += " = &_OBJC_PROTOCOL_"; + Result += (*I)->getNameAsString(); + Result += ";\n"; + } + Result += "#pragma data_seg(pop)\n\n"; + } + Result += "#pragma section(\".objc_module_info$B\",long,read,write)\n"; + Result += "#pragma data_seg(push, \".objc_module_info$B\")\n"; + Result += "static struct _objc_module *_POINTER_OBJC_MODULES = "; + Result += "&_OBJC_MODULES;\n"; + Result += "#pragma data_seg(pop)\n\n"; + } +} + +/// RewriteObjCCategoryImplDecl - Rewrite metadata for each category +/// implementation. +void RewriteObjCFragileABI::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, + std::string &Result) { + ObjCInterfaceDecl *ClassDecl = IDecl->getClassInterface(); + // Find category declaration for this implementation. + ObjCCategoryDecl *CDecl; + for (CDecl = ClassDecl->getCategoryList(); CDecl; + CDecl = CDecl->getNextClassCategory()) + if (CDecl->getIdentifier() == IDecl->getIdentifier()) + break; + + std::string FullCategoryName = ClassDecl->getNameAsString(); + FullCategoryName += '_'; + FullCategoryName += IDecl->getNameAsString(); + + // Build _objc_method_list for class's instance methods if needed + SmallVector<ObjCMethodDecl *, 32> + InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); + + // If any of our property implementations have associated getters or + // setters, produce metadata for them as well. + for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), + PropEnd = IDecl->propimpl_end(); + Prop != PropEnd; ++Prop) { + if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + continue; + if (!(*Prop)->getPropertyIvarDecl()) + continue; + ObjCPropertyDecl *PD = (*Prop)->getPropertyDecl(); + if (!PD) + continue; + if (ObjCMethodDecl *Getter = PD->getGetterMethodDecl()) + InstanceMethods.push_back(Getter); + if (PD->isReadOnly()) + continue; + if (ObjCMethodDecl *Setter = PD->getSetterMethodDecl()) + InstanceMethods.push_back(Setter); + } + RewriteObjCMethodsMetaData(InstanceMethods.begin(), InstanceMethods.end(), + true, "CATEGORY_", FullCategoryName.c_str(), + Result); + + // Build _objc_method_list for class's class methods if needed + RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), + false, "CATEGORY_", FullCategoryName.c_str(), + Result); + + // Protocols referenced in class declaration? + // Null CDecl is case of a category implementation with no category interface + if (CDecl) + RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", + FullCategoryName, Result); + /* struct _objc_category { + char *category_name; + char *class_name; + struct _objc_method_list *instance_methods; + struct _objc_method_list *class_methods; + struct _objc_protocol_list *protocols; + // Objective-C 1.0 extensions + uint32_t size; // sizeof (struct _objc_category) + struct _objc_property_list *instance_properties; // category's own + // @property decl. + }; + */ + + static bool objc_category = false; + if (!objc_category) { + Result += "\nstruct _objc_category {\n"; + Result += "\tchar *category_name;\n"; + Result += "\tchar *class_name;\n"; + Result += "\tstruct _objc_method_list *instance_methods;\n"; + Result += "\tstruct _objc_method_list *class_methods;\n"; + Result += "\tstruct _objc_protocol_list *protocols;\n"; + Result += "\tunsigned int size;\n"; + Result += "\tstruct _objc_property_list *instance_properties;\n"; + Result += "};\n"; + objc_category = true; + } + Result += "\nstatic struct _objc_category _OBJC_CATEGORY_"; + Result += FullCategoryName; + Result += " __attribute__ ((used, section (\"__OBJC, __category\")))= {\n\t\""; + Result += IDecl->getNameAsString(); + Result += "\"\n\t, \""; + Result += ClassDecl->getNameAsString(); + Result += "\"\n"; + + if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { + Result += "\t, (struct _objc_method_list *)" + "&_OBJC_CATEGORY_INSTANCE_METHODS_"; + Result += FullCategoryName; + Result += "\n"; + } + else + Result += "\t, 0\n"; + if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { + Result += "\t, (struct _objc_method_list *)" + "&_OBJC_CATEGORY_CLASS_METHODS_"; + Result += FullCategoryName; + Result += "\n"; + } + else + Result += "\t, 0\n"; + + if (CDecl && CDecl->protocol_begin() != CDecl->protocol_end()) { + Result += "\t, (struct _objc_protocol_list *)&_OBJC_CATEGORY_PROTOCOLS_"; + Result += FullCategoryName; + Result += "\n"; + } + else + Result += "\t, 0\n"; + Result += "\t, sizeof(struct _objc_category), 0\n};\n"; +} + +// RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or +/// class methods. +template<typename MethodIterator> +void RewriteObjCFragileABI::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, + MethodIterator MethodEnd, + bool IsInstanceMethod, + StringRef prefix, + StringRef ClassName, + std::string &Result) { + if (MethodBegin == MethodEnd) return; + + if (!objc_impl_method) { + /* struct _objc_method { + SEL _cmd; + char *method_types; + void *_imp; + } + */ + Result += "\nstruct _objc_method {\n"; + Result += "\tSEL _cmd;\n"; + Result += "\tchar *method_types;\n"; + Result += "\tvoid *_imp;\n"; + Result += "};\n"; + + objc_impl_method = true; + } + + // Build _objc_method_list for class's methods if needed + + /* struct { + struct _objc_method_list *next_method; + int method_count; + struct _objc_method method_list[]; + } + */ + unsigned NumMethods = std::distance(MethodBegin, MethodEnd); + Result += "\nstatic struct {\n"; + Result += "\tstruct _objc_method_list *next_method;\n"; + Result += "\tint method_count;\n"; + Result += "\tstruct _objc_method method_list["; + Result += utostr(NumMethods); + Result += "];\n} _OBJC_"; + Result += prefix; + Result += IsInstanceMethod ? "INSTANCE" : "CLASS"; + Result += "_METHODS_"; + Result += ClassName; + Result += " __attribute__ ((used, section (\"__OBJC, __"; + Result += IsInstanceMethod ? "inst" : "cls"; + Result += "_meth\")))= "; + Result += "{\n\t0, " + utostr(NumMethods) + "\n"; + + Result += "\t,{{(SEL)\""; + Result += (*MethodBegin)->getSelector().getAsString().c_str(); + std::string MethodTypeString; + Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); + Result += "\", \""; + Result += MethodTypeString; + Result += "\", (void *)"; + Result += MethodInternalNames[*MethodBegin]; + Result += "}\n"; + for (++MethodBegin; MethodBegin != MethodEnd; ++MethodBegin) { + Result += "\t ,{(SEL)\""; + Result += (*MethodBegin)->getSelector().getAsString().c_str(); + std::string MethodTypeString; + Context->getObjCEncodingForMethodDecl(*MethodBegin, MethodTypeString); + Result += "\", \""; + Result += MethodTypeString; + Result += "\", (void *)"; + Result += MethodInternalNames[*MethodBegin]; + Result += "}\n"; + } + Result += "\t }\n};\n"; +} + +Stmt *RewriteObjCFragileABI::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV) { + SourceRange OldRange = IV->getSourceRange(); + Expr *BaseExpr = IV->getBase(); + + // Rewrite the base, but without actually doing replaces. + { + DisableReplaceStmtScope S(*this); + BaseExpr = cast<Expr>(RewriteFunctionBodyOrGlobalInitializer(BaseExpr)); + IV->setBase(BaseExpr); + } + + ObjCIvarDecl *D = IV->getDecl(); + + Expr *Replacement = IV; + if (CurMethodDef) { + if (BaseExpr->getType()->isObjCObjectPointerType()) { + const ObjCInterfaceType *iFaceDecl = + dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); + assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null"); + // lookup which class implements the instance variable. + ObjCInterfaceDecl *clsDeclared = 0; + iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), + clsDeclared); + assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); + + // Synthesize an explicit cast to gain access to the ivar. + std::string RecName = clsDeclared->getIdentifier()->getName(); + RecName += "_IMPL"; + IdentifierInfo *II = &Context->Idents.get(RecName); + RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, + SourceLocation(), SourceLocation(), + II); + assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); + QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); + CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, + CK_BitCast, + IV->getBase()); + // Don't forget the parens to enforce the proper binding. + ParenExpr *PE = new (Context) ParenExpr(OldRange.getBegin(), + OldRange.getEnd(), + castExpr); + if (IV->isFreeIvar() && + declaresSameEntity(CurMethodDef->getClassInterface(), iFaceDecl->getDecl())) { + MemberExpr *ME = new (Context) MemberExpr(PE, true, D, + IV->getLocation(), + D->getType(), + VK_LValue, OK_Ordinary); + Replacement = ME; + } else { + IV->setBase(PE); + } + } + } else { // we are outside a method. + assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method"); + + // Explicit ivar refs need to have a cast inserted. + // FIXME: consider sharing some of this code with the code above. + if (BaseExpr->getType()->isObjCObjectPointerType()) { + const ObjCInterfaceType *iFaceDecl = + dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType()); + // lookup which class implements the instance variable. + ObjCInterfaceDecl *clsDeclared = 0; + iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), + clsDeclared); + assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); + + // Synthesize an explicit cast to gain access to the ivar. + std::string RecName = clsDeclared->getIdentifier()->getName(); + RecName += "_IMPL"; + IdentifierInfo *II = &Context->Idents.get(RecName); + RecordDecl *RD = RecordDecl::Create(*Context, TTK_Struct, TUDecl, + SourceLocation(), SourceLocation(), + II); + assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); + QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); + CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT, + CK_BitCast, + IV->getBase()); + // Don't forget the parens to enforce the proper binding. + ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), + IV->getBase()->getLocEnd(), castExpr); + // Cannot delete IV->getBase(), since PE points to it. + // Replace the old base with the cast. This is important when doing + // embedded rewrites. For example, [newInv->_container addObject:0]. + IV->setBase(PE); + } + } + + ReplaceStmtWithRange(IV, Replacement, OldRange); + return Replacement; +} + |