diff options
author | Steve Naroff <snaroff@apple.com> | 2009-04-29 16:37:50 +0000 |
---|---|---|
committer | Steve Naroff <snaroff@apple.com> | 2009-04-29 16:37:50 +0000 |
commit | d98037132f2223f463d95361aa03d8ae0d98f64a (patch) | |
tree | 9004f0ae4d93b6820a353ba147e4c59273119dd1 /clang/tools | |
parent | debdc1d732e3a0cdd03dc4138f82851413fc2b45 (diff) | |
download | bcm5719-llvm-d98037132f2223f463d95361aa03d8ae0d98f64a.tar.gz bcm5719-llvm-d98037132f2223f463d95361aa03d8ae0d98f64a.zip |
Integrate 3 months of ObjC rewriter fixes (from the Apple/objective-rewrite branch).
llvm-svn: 70385
Diffstat (limited to 'clang/tools')
-rw-r--r-- | clang/tools/clang-cc/PrintPreprocessedOutput.cpp | 5 | ||||
-rw-r--r-- | clang/tools/clang-cc/RewriteObjC.cpp | 491 |
2 files changed, 281 insertions, 215 deletions
diff --git a/clang/tools/clang-cc/PrintPreprocessedOutput.cpp b/clang/tools/clang-cc/PrintPreprocessedOutput.cpp index a2047fa0063..c7eb72b00ea 100644 --- a/clang/tools/clang-cc/PrintPreprocessedOutput.cpp +++ b/clang/tools/clang-cc/PrintPreprocessedOutput.cpp @@ -422,9 +422,10 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, // to -C or -CC. PP.SetCommentRetentionState(EnableCommentOutput, EnableMacroCommentOutput); - // Open the output buffer. + // Open the output buffer using "Binary" mode. On Windows, this distinction + // is important (to surpress automatic LF->CFLF conversion). std::string Err; - llvm::raw_fd_ostream OS(OutFile.empty() ? "-" : OutFile.c_str(), false, Err); + llvm::raw_fd_ostream OS(OutFile.empty() ? "-" : OutFile.c_str(), true, Err); if (!Err.empty()) { fprintf(stderr, "%s\n", Err.c_str()); exit(1); diff --git a/clang/tools/clang-cc/RewriteObjC.cpp b/clang/tools/clang-cc/RewriteObjC.cpp index 95b50b832e4..37dd52485d6 100644 --- a/clang/tools/clang-cc/RewriteObjC.cpp +++ b/clang/tools/clang-cc/RewriteObjC.cpp @@ -58,6 +58,8 @@ namespace { llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames; llvm::SmallVector<Stmt *, 32> Stmts; llvm::SmallVector<int, 8> ObjCBcLabelNo; + // Remember all the @protocol(<expr>) expressions. + llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls; unsigned NumObjCStringLiterals; @@ -70,7 +72,6 @@ namespace { FunctionDecl *GetMetaClassFunctionDecl; FunctionDecl *SelGetUidFunctionDecl; FunctionDecl *CFStringFunctionDecl; - FunctionDecl *GetProtocolFunctionDecl; FunctionDecl *SuperContructorFunctionDecl; // ObjC string constant support. @@ -85,6 +86,9 @@ namespace { RecordDecl *SuperStructDecl; RecordDecl *ConstantStringDecl; + TypeDecl *ProtocolTypeDecl; + QualType getProtocolType(); + // Needed for header files being rewritten bool IsHeader; @@ -276,7 +280,6 @@ namespace { void SynthGetClassFunctionDecl(); void SynthGetMetaClassFunctionDecl(); void SynthSelGetUidFunctionDecl(); - void SynthGetProtocolFunctionDecl(); void SynthSuperContructorFunctionDecl(); // Metadata emission. @@ -294,11 +297,14 @@ namespace { const char *ClassName, std::string &Result); - void RewriteObjCProtocolsMetaData(const ObjCList<ObjCProtocolDecl> - &Protocols, - const char *prefix, - const char *ClassName, - std::string &Result); + void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol, + const char *prefix, + const char *ClassName, + std::string &Result); + void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots, + const char *prefix, + const char *ClassName, + std::string &Result); void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, std::string &Result); void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl, @@ -317,7 +323,7 @@ namespace { // Block specific rewrite rules. void RewriteBlockCall(CallExpr *Exp); void RewriteBlockPointerDecl(NamedDecl *VD); - void RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD); + Stmt *RewriteBlockDeclRefExpr(BlockDeclRefExpr *VD); void RewriteBlockPointerFunctionArgs(FunctionDecl *FD); std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, @@ -365,6 +371,15 @@ namespace { FunctionDecl *SynthBlockInitFunctionDecl(const char *name); Stmt *SynthBlockInitExpr(BlockExpr *Exp); + + void QuoteDoublequotes(std::string &From, std::string &To) { + for(unsigned i = 0; i < From.length(); i++) { + if (From[i] == '"') + To += "\\\""; + else + To += From[i]; + } + } }; } @@ -434,13 +449,13 @@ void RewriteObjC::Initialize(ASTContext &context) { GetMetaClassFunctionDecl = 0; SelGetUidFunctionDecl = 0; CFStringFunctionDecl = 0; - GetProtocolFunctionDecl = 0; ConstantStringClassReference = 0; NSStringRecord = 0; CurMethodDef = 0; CurFunctionDef = 0; GlobalVarDecl = 0; SuperStructDecl = 0; + ProtocolTypeDecl = 0; ConstantStringDecl = 0; BcLabelCount = 0; SuperContructorFunctionDecl = 0; @@ -698,7 +713,6 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, Getr += "return " + getIvarAccessString(ClassDecl, OID); Getr += "; }"; InsertText(onePastSemiLoc, Getr.c_str(), Getr.size()); - if (PD->isReadOnly()) return; @@ -913,7 +927,7 @@ void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, ResultStr += " *"; } else - ResultStr += Context->getObjCIdType().getAsString(); + ResultStr += Context->getObjCClassType().getAsString(); ResultStr += " self, "; ResultStr += Context->getObjCSelType().getAsString(); @@ -1490,6 +1504,8 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { SourceLocation lastCurlyLoc = startLoc; buf = "}\nelse {\n"; buf += " _rethrow = objc_exception_extract(&_stack);\n"; + buf += "}\n"; + buf += "{ /* implicit finally clause */\n"; buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; buf += " objc_sync_exit("; Expr *syncExpr = new (Context) CStyleCastExpr(Context->getObjCIdType(), @@ -1943,21 +1959,6 @@ void RewriteObjC::SynthSelGetUidFunctionDecl() { FunctionDecl::Extern, false); } -// SynthGetProtocolFunctionDecl - Protocol objc_getProtocol(const char *proto); -void RewriteObjC::SynthGetProtocolFunctionDecl() { - IdentifierInfo *SelGetProtoIdent = &Context->Idents.get("objc_getProtocol"); - llvm::SmallVector<QualType, 16> ArgTys; - ArgTys.push_back(Context->getPointerType( - Context->CharTy.getQualifiedType(QualType::Const))); - QualType getFuncType = Context->getFunctionType(Context->getObjCProtoType(), - &ArgTys[0], ArgTys.size(), - false /*isVariadic*/, 0); - GetProtocolFunctionDecl = FunctionDecl::Create(*Context, TUDecl, - SourceLocation(), - SelGetProtoIdent, getFuncType, - FunctionDecl::Extern, false); -} - void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { // declared in <objc/objc.h> if (FD->getIdentifier() && @@ -2258,8 +2259,8 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl; // May need to use objc_msgSend_stret() as well. FunctionDecl *MsgSendStretFlavor = 0; - if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) { - QualType resultType = OMD->getResultType(); + if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) { + QualType resultType = mDecl->getResultType(); if (resultType->isStructureType() || resultType->isUnionType()) MsgSendStretFlavor = MsgSendStretFunctionDecl; else if (resultType->isRealFloatingType()) @@ -2286,10 +2287,14 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { llvm::SmallVector<Expr*, 4> InitExprs; // set the receiver to self, the first argument to all methods. - InitExprs.push_back(new (Context) DeclRefExpr( - CurMethodDef->getSelfDecl(), - Context->getObjCIdType(), - SourceLocation())); + InitExprs.push_back( + new (Context) CStyleCastExpr(Context->getObjCIdType(), + new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(), + Context->getObjCIdType(), + SourceLocation()), + Context->getObjCIdType(), + SourceLocation(), SourceLocation())); // set the 'receiver'. + llvm::SmallVector<Expr*, 8> ClsExprs; QualType argType = Context->getPointerType(Context->CharTy); ClsExprs.push_back(StringLiteral::Create(*Context, @@ -2463,9 +2468,10 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { } } MsgExprs.push_back(userExpr); - // We've transferred the ownership to MsgExprs. Null out the argument in - // the original expression, since we will delete it below. - Exp->setArg(i, 0); + // We've transferred the ownership to MsgExprs. For now, we *don't* null + // out the argument in the original expression (since we aren't deleting + // the ObjCMessageExpr). See RewritePropertySetter() usage for more info. + //Exp->setArg(i, 0); } // Generate the funky cast. CastExpr *cast; @@ -2579,13 +2585,13 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) { new (Context) ConditionalOperator(lessThanExpr, CE, STCE, returnType); ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), CondExpr); } + // delete Exp; leak for now, see RewritePropertySetter() usage for more info. return ReplacingStmt; } Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { Stmt *ReplacingStmt = SynthMessageExpr(Exp); - //ReplacingStmt->dump(); // Now do the actual rewrite. ReplaceStmt(Exp, ReplacingStmt); @@ -2593,24 +2599,37 @@ Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) { return ReplacingStmt; } +// typedef struct objc_object Protocol; +QualType RewriteObjC::getProtocolType() { + if (!ProtocolTypeDecl) { + ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl, + SourceLocation(), + &Context->Idents.get("Protocol"), + Context->getObjCIdType()); + } + return Context->getTypeDeclType(ProtocolTypeDecl); +} + /// RewriteObjCProtocolExpr - Rewrite a protocol expression into -/// call to objc_getProtocol("proto-name"). +/// a synthesized/forward data reference (to the protocol's metadata). +/// The forward references (and metadata) are generated in +/// RewriteObjC::HandleTranslationUnit(). Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) { - if (!GetProtocolFunctionDecl) - SynthGetProtocolFunctionDecl(); - // Create a call to objc_getProtocol("ProtocolName"). - llvm::SmallVector<Expr*, 8> ProtoExprs; - QualType argType = Context->getPointerType(Context->CharTy); - ProtoExprs.push_back(StringLiteral::Create(*Context, - Exp->getProtocol()->getNameAsCString(), - strlen(Exp->getProtocol()->getNameAsCString()), - false, argType, SourceLocation())); - CallExpr *ProtoExp = SynthesizeCallToFunctionDecl(GetProtocolFunctionDecl, - &ProtoExprs[0], - ProtoExprs.size()); - ReplaceStmt(Exp, ProtoExp); - // delete Exp; leak for now, see RewritePropertySetter() usage for more info. - return ProtoExp; + std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString(); + IdentifierInfo *ID = &Context->Idents.get(Name); + VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(), + ID, QualType()/*UNUSED*/, VarDecl::Extern); + DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation()); + Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, + Context->getPointerType(DRE->getType()), + SourceLocation()); + CastExpr *castExpr = new (Context) CStyleCastExpr(DerefExpr->getType(), DerefExpr, + DerefExpr->getType(), + SourceLocation(), SourceLocation()); + ReplaceStmt(Exp, castExpr); + ProtocolExprDecls.insert(Exp->getProtocol()); + // delete Exp; leak for now, see RewritePropertySetter() usage for more info. + return castExpr; } @@ -2847,159 +2866,165 @@ void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin, Result += "\t }\n};\n"; } -/// RewriteObjCProtocolsMetaData - Rewrite protocols meta-data. +/// RewriteObjCProtocolMetaData - Rewrite protocols meta-data. void RewriteObjC:: -RewriteObjCProtocolsMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, - const char *prefix, - const char *ClassName, - std::string &Result) { +RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, + const char *ClassName, std::string &Result) { static bool objc_protocol_methods = false; - if (Protocols.empty()) return; - - for (unsigned i = 0; i != Protocols.size(); i++) { - ObjCProtocolDecl *PDecl = Protocols[i]; - // 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 += "\tSEL _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)) - continue; - + + // 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(*Context) != PDecl->instmeth_end(*Context)) { unsigned NumMethods = std::distance(PDecl->instmeth_begin(*Context), PDecl->instmeth_end(*Context)); - /* 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 protocols["; - 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(*Context), - E = PDecl->instmeth_end(*Context); - I != E; ++I) { - if (I == PDecl->instmeth_begin(*Context)) - Result += "\t ,{{(SEL)\""; - else - Result += "\t ,{(SEL)\""; - Result += (*I)->getSelector().getAsString().c_str(); - std::string MethodTypeString; - Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); - Result += "\", \""; - Result += MethodTypeString; - Result += "\"}\n"; - } - Result += "\t }\n};\n"; - } + /* 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 class methods declared in this protocol. - unsigned NumMethods = std::distance(PDecl->classmeth_begin(*Context), - PDecl->classmeth_end(*Context)); - 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 protocols["; - 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(*Context), - E = PDecl->classmeth_end(*Context); - I != E; ++I) { - if (I == PDecl->classmeth_begin(*Context)) - Result += "\t ,{{(SEL)\""; - else - Result += "\t ,{(SEL)\""; - Result += (*I)->getSelector().getAsString().c_str(); - std::string MethodTypeString; - Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); - Result += "\", \""; - Result += MethodTypeString; - Result += "\"}\n"; - } - Result += "\t }\n};\n"; + // Output instance methods declared in this protocol. + for (ObjCProtocolDecl::instmeth_iterator + I = PDecl->instmeth_begin(*Context), + E = PDecl->instmeth_end(*Context); + I != E; ++I) { + if (I == PDecl->instmeth_begin(*Context)) + Result += "\t ,{{(struct objc_selector *)\""; + else + Result += "\t ,{(struct objc_selector *)\""; + Result += (*I)->getSelector().getAsString().c_str(); + std::string MethodTypeString; + Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); + Result += "\", \""; + Result += MethodTypeString; + Result += "\"}\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; - }; + Result += "\t }\n};\n"; + } + + // Output class methods declared in this protocol. + unsigned NumMethods = std::distance(PDecl->classmeth_begin(*Context), + PDecl->classmeth_end(*Context)); + if (NumMethods > 0) { + /* struct _objc_protocol_method_list { + int protocol_method_count; + struct protocol_methods protocols[]; + } */ - 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 += "\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, __protocol\")))= " - "{\n\t0, \""; - Result += PDecl->getNameAsString(); - Result += "\", 0, "; - if (PDecl->instmeth_begin(*Context) != PDecl->instmeth_end(*Context)) { - Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; - Result += PDecl->getNameAsString(); - Result += ", "; - } - else - Result += "0, "; - if (PDecl->classmeth_begin(*Context) != PDecl->classmeth_end(*Context)) { - Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; - Result += PDecl->getNameAsString(); - Result += "\n"; + 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(*Context), + E = PDecl->classmeth_end(*Context); + I != E; ++I) { + if (I == PDecl->classmeth_begin(*Context)) + Result += "\t ,{{(struct objc_selector *)\""; + else + Result += "\t ,{(struct objc_selector *)\""; + Result += (*I)->getSelector().getAsString().c_str(); + std::string MethodTypeString; + Context->getObjCEncodingForMethodDecl((*I), MethodTypeString); + Result += "\", \""; + Result += MethodTypeString; + Result += "\"}\n"; } - else - Result += "0\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"; - // Mark this protocol as having been generated. - if (!ObjCSynthesizedProtocols.insert(PDecl)) - assert(false && "protocol already synthesized"); + 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(*Context) != PDecl->instmeth_end(*Context)) { + Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; + Result += PDecl->getNameAsString(); + Result += ", "; } + else + Result += "0, "; + if (PDecl->classmeth_begin(*Context) != PDecl->classmeth_end(*Context)) { + 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)) + assert(false && "protocol already synthesized"); + +} + +void RewriteObjC:: +RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, + const char *prefix, const char *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; @@ -3033,6 +3058,7 @@ RewriteObjCProtocolsMetaData(const ObjCList<ObjCProtocolDecl> &Protocols, Result += "\t }\n};\n"; } + /// RewriteObjCCategoryImplDecl - Rewrite metadata for each category /// implementation. void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, @@ -3048,7 +3074,7 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, std::string FullCategoryName = ClassDecl->getNameAsString(); FullCategoryName += '_'; FullCategoryName += IDecl->getNameAsString(); - + // Build _objc_method_list for class's instance methods if needed llvm::SmallVector<ObjCMethodDecl *, 32> InstanceMethods(IDecl->instmeth_begin(*Context), @@ -3086,9 +3112,8 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, // Protocols referenced in class declaration? // Null CDecl is case of a category implementation with no category interface if (CDecl) - RewriteObjCProtocolsMetaData(CDecl->getReferencedProtocols(), "CATEGORY", - FullCategoryName.c_str(), Result); - + RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), "CATEGORY", + FullCategoryName.c_str(), Result); /* struct _objc_category { char *category_name; char *class_name; @@ -3240,8 +3265,9 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, Result += "\t,{{\""; Result += (*IVI)->getNameAsString(); Result += "\", \""; - std::string StrEncoding; - Context->getObjCEncodingForType((*IVI)->getType(), StrEncoding); + std::string TmpString, StrEncoding; + Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); + QuoteDoublequotes(TmpString, StrEncoding); Result += StrEncoding; Result += "\", "; SynthesizeIvarOffsetComputation(IDecl, *IVI, Result); @@ -3250,8 +3276,9 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, Result += "\t ,{\""; Result += (*IVI)->getNameAsString(); Result += "\", \""; - std::string StrEncoding; - Context->getObjCEncodingForType((*IVI)->getType(), StrEncoding); + std::string TmpString, StrEncoding; + Context->getObjCEncodingForType((*IVI)->getType(), TmpString, *IVI); + QuoteDoublequotes(TmpString, StrEncoding); Result += StrEncoding; Result += "\", "; SynthesizeIvarOffsetComputation(IDecl, (*IVI), Result); @@ -3294,10 +3321,9 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, false, "", IDecl->getNameAsCString(), Result); // Protocols referenced in class declaration? - RewriteObjCProtocolsMetaData(CDecl->getReferencedProtocols(), - "CLASS", CDecl->getNameAsCString(), Result); + RewriteObjCProtocolListMetaData(CDecl->getReferencedProtocols(), + "CLASS", CDecl->getNameAsCString(), Result); - // Declaration of class/meta-class metadata /* struct _objc_class { struct _objc_class *isa; // or const char *root_class_name when metadata @@ -3462,7 +3488,7 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &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 @@ -3527,6 +3553,19 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) { Result += "};\n\n"; if (LangOpts.Microsoft) { + 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 = "; @@ -3715,9 +3754,12 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, S += FieldName + "; // by ref\n"; } // Finish writing the constructor. - // FIXME: handle NSConcreteGlobalBlock. Constructor += ", int flags=0) {\n"; - Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof("; + if (GlobalVarDecl) + Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; + else + Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; + Constructor += " impl.Size = sizeof("; Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n"; if (hasCopyDisposeHelpers) @@ -3747,9 +3789,12 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, } } else { // Finish writing the constructor. - // FIXME: handle NSConcreteGlobalBlock. Constructor += ", int flags=0) {\n"; - Constructor += " impl.isa = 0/*&_NSConcreteStackBlock*/;\n impl.Size = sizeof("; + if (GlobalVarDecl) + Constructor += " impl.isa = &_NSConcreteGlobalBlock;\n"; + else + Constructor += " impl.isa = &_NSConcreteStackBlock;\n"; + Constructor += " impl.Size = sizeof("; Constructor += Tag + ");\n impl.Flags = flags;\n impl.FuncPtr = fp;\n"; if (hasCopyDisposeHelpers) Constructor += " copy = copyHelp;\n dispose = disposeHelp;\n"; @@ -3940,7 +3985,20 @@ void RewriteObjC::RewriteBlockCall(CallExpr *Exp) { ReplaceStmt(Exp, BlockCall); } -void RewriteObjC::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) { +// We need to return the rewritten expression to handle cases where the +// BlockDeclRefExpr is embedded in another expression being rewritten. +// For example: +// +// int main() { +// __block Foo *f; +// __block int i; +// +// void (^myblock)() = ^() { +// [f test]; // f is a BlockDeclRefExpr embedded in a message (which is being rewritten). +// i = 77; +// }; +//} +Stmt *RewriteObjC::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) { // FIXME: Add more elaborate code generation required by the ABI. Expr *DerefExpr = new (Context) UnaryOperator(BDRE, UnaryOperator::Deref, Context->getPointerType(BDRE->getType()), @@ -3948,6 +4006,7 @@ void RewriteObjC::RewriteBlockDeclRefExpr(BlockDeclRefExpr *BDRE) { // Need parens to enforce precedence. ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), DerefExpr); ReplaceStmt(BDRE, PE); + return PE; } void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { @@ -4447,7 +4506,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { // Handle blocks rewriting. if (BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) { if (BDRE->isByRef()) - RewriteBlockDeclRefExpr(BDRE); + return RewriteBlockDeclRefExpr(BDRE); } if (CallExpr *CE = dyn_cast<CallExpr>(S)) { if (CE->getCallee()->getType()->isBlockPointerType()) { @@ -4625,12 +4684,17 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) { RewriteInclude(); + // Here's a great place to add any extra declarations that may be needed. + // Write out meta data for each @protocol(<expr>). + for (llvm::SmallPtrSet<ObjCProtocolDecl *,8>::iterator I = ProtocolExprDecls.begin(), + E = ProtocolExprDecls.end(); I != E; ++I) + RewriteObjCProtocolMetaData(*I, "", "", Preamble); + InsertText(SM->getLocForStartOfFile(MainFileID), Preamble.c_str(), Preamble.size(), false); - if (ClassImplementation.size() || CategoryImplementation.size()) RewriteImplementations(); - + // Get the buffer corresponding to MainFileID. If we haven't changed it, then // we are done. if (const RewriteBuffer *RewriteBuf = @@ -4641,7 +4705,8 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) { fprintf(stderr, "No changes\n"); } - if (ClassImplementation.size() || CategoryImplementation.size()) { + if (ClassImplementation.size() || CategoryImplementation.size() || + ProtocolExprDecls.size()) { // Rewrite Objective-c meta data* std::string ResultStr; SynthesizeMetaDataIntoBuffer(ResultStr); |