diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-02-16 09:31:36 +0000 |
commit | fd035e6496665b1f1197868e21cb0a4594e8db6e (patch) | |
tree | 53010172e19c77ea447bcd89e117cda052ab52e0 /lib/Frontend/RewriteObjC.cpp | |
parent | 2fce988e86bc01829142e4362d4eff1af0925147 (diff) | |
download | FreeBSD-src-fd035e6496665b1f1197868e21cb0a4594e8db6e.zip FreeBSD-src-fd035e6496665b1f1197868e21cb0a4594e8db6e.tar.gz |
Update clang to r96341.
Diffstat (limited to 'lib/Frontend/RewriteObjC.cpp')
-rw-r--r-- | lib/Frontend/RewriteObjC.cpp | 448 |
1 files changed, 274 insertions, 174 deletions
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index 35d8dde..9dade66 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -124,8 +124,10 @@ namespace { llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs; // Block related declarations. - llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls; - llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls; + llvm::SmallVector<ValueDecl *, 8> BlockByCopyDecls; + llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDeclsPtrSet; + llvm::SmallVector<ValueDecl *, 8> BlockByRefDecls; + llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet; llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo; llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls; @@ -212,11 +214,10 @@ namespace { << Old->getSourceRange(); } - void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen, + void InsertText(SourceLocation Loc, llvm::StringRef Str, bool InsertAfter = true) { // If insertion succeeded or warning disabled return with no warning. - if (!Rewrite.InsertText(Loc, llvm::StringRef(StrData, StrLen), - InsertAfter) || + if (!Rewrite.InsertText(Loc, Str, InsertAfter) || SilenceRewriteMacroWarning) return; @@ -232,10 +233,9 @@ namespace { } void ReplaceText(SourceLocation Start, unsigned OrigLength, - const char *NewStr, unsigned NewLength) { + llvm::StringRef Str) { // If removal succeeded or warning disabled return with no warning. - if (!Rewrite.ReplaceText(Start, OrigLength, - llvm::StringRef(NewStr, NewLength)) || + if (!Rewrite.ReplaceText(Start, OrigLength, Str) || SilenceRewriteMacroWarning) return; @@ -263,6 +263,7 @@ namespace { void RewriteFunctionDecl(FunctionDecl *FD); void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD); void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl); + void RewriteTypeOfDecl(VarDecl *VD); void RewriteObjCQualifiedInterfaceTypes(Expr *E); bool needToScanForQualifiers(QualType T); ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr); @@ -278,7 +279,9 @@ namespace { ParentMap *PropParentMap; // created lazily. Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp); - Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart); + Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart, + bool &replaced); + Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced); Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr); Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, SourceRange SrcRange); @@ -632,6 +635,9 @@ void RewriteObjC::Initialize(ASTContext &context) { //===----------------------------------------------------------------------===// void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { + if (Diags.hasErrorOccurred()) + return; + // Two cases: either the decl could be in the main file, or it could be in a // #included file. If the former, rewrite it now. If the later, check to see // if we rewrote the #include/#import. @@ -681,7 +687,6 @@ void RewriteObjC::RewriteInclude() { const char *MainBufStart = MainBuf.first; const char *MainBufEnd = MainBuf.second; size_t ImportLen = strlen("import"); - size_t IncludeLen = strlen("include"); // Loop over the whole file, looking for includes. for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) { @@ -695,7 +700,7 @@ void RewriteObjC::RewriteInclude() { // replace import with include SourceLocation ImportLoc = LocStart.getFileLocWithOffset(BufPtr-MainBufStart); - ReplaceText(ImportLoc, ImportLen, "include", IncludeLen); + ReplaceText(ImportLoc, ImportLen, "include"); BufPtr += ImportLen; } } @@ -728,7 +733,7 @@ void RewriteObjC::RewriteTabs() { TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart); // Rewrite the single tab character into a sequence of spaces. - ReplaceText(TabLoc, 1, " ", Spaces); + ReplaceText(TabLoc, 1, llvm::StringRef(" ", Spaces)); } } @@ -746,7 +751,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, ObjCImplementationDecl *IMD, ObjCCategoryImplDecl *CID) { SourceLocation startLoc = PID->getLocStart(); - InsertText(startLoc, "// ", 3); + InsertText(startLoc, "// "); const char *startBuf = SM->getCharacterData(startLoc); assert((*startBuf == '@') && "bogus @synthesize location"); const char *semiBuf = strchr(startBuf, ';'); @@ -774,7 +779,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, // See objc-act.c:objc_synthesize_new_getter() for details. Getr += "return " + getIvarAccessString(ClassDecl, OID); Getr += "; }"; - InsertText(onePastSemiLoc, Getr.c_str(), Getr.size()); + InsertText(onePastSemiLoc, Getr); if (PD->isReadOnly()) return; @@ -789,7 +794,7 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, Setr += getIvarAccessString(ClassDecl, OID) + " = "; Setr += PD->getNameAsCString(); Setr += "; }"; - InsertText(onePastSemiLoc, Setr.c_str(), Setr.size()); + InsertText(onePastSemiLoc, Setr); } void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { @@ -828,8 +833,7 @@ void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) { } // Replace the @class with typedefs corresponding to the classes. - ReplaceText(startLoc, semiPtr-startBuf+1, - typedefString.c_str(), typedefString.size()); + ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); } void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { @@ -842,17 +846,17 @@ void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { if (SM->getInstantiationLineNumber(LocEnd) > SM->getInstantiationLineNumber(LocStart)) { - InsertText(LocStart, "#if 0\n", 6); - ReplaceText(LocEnd, 1, ";\n#endif\n", 9); + InsertText(LocStart, "#if 0\n"); + ReplaceText(LocEnd, 1, ";\n#endif\n"); } else { - InsertText(LocStart, "// ", 3); + InsertText(LocStart, "// "); } } void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) { SourceLocation Loc = prop->getAtLoc(); - ReplaceText(Loc, 0, "// ", 3); + ReplaceText(Loc, 0, "// "); // FIXME: handle properties that are declared across multiple lines. } @@ -860,8 +864,12 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { SourceLocation LocStart = CatDecl->getLocStart(); // FIXME: handle category headers that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); + ReplaceText(LocStart, 0, "// "); + for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(), + E = CatDecl->prop_end(); I != E; ++I) + RewriteProperty(*I); + for (ObjCCategoryDecl::instmeth_iterator I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); I != E; ++I) @@ -872,7 +880,7 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { RewriteMethodDeclaration(*I); // Lastly, comment out the @end. - ReplaceText(CatDecl->getAtEndRange().getBegin(), 0, "// ", 3); + ReplaceText(CatDecl->getAtEndRange().getBegin(), 0, "// "); } void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { @@ -881,7 +889,7 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { SourceLocation LocStart = PDecl->getLocStart(); // FIXME: handle protocol headers that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); + ReplaceText(LocStart, 0, "// "); for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); @@ -894,24 +902,20 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { // Lastly, comment out the @end. SourceLocation LocEnd = PDecl->getAtEndRange().getBegin(); - ReplaceText(LocEnd, 0, "// ", 3); + ReplaceText(LocEnd, 0, "// "); // Must comment out @optional/@required const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); for (const char *p = startBuf; p < endBuf; p++) { if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) { - std::string CommentedOptional = "/* @optional */"; SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); - ReplaceText(OptionalLoc, strlen("@optional"), - CommentedOptional.c_str(), CommentedOptional.size()); + ReplaceText(OptionalLoc, strlen("@optional"), "/* @optional */"); } else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) { - std::string CommentedRequired = "/* @required */"; SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf); - ReplaceText(OptionalLoc, strlen("@required"), - CommentedRequired.c_str(), CommentedRequired.size()); + ReplaceText(OptionalLoc, strlen("@required"), "/* @required */"); } } @@ -922,7 +926,7 @@ void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) { if (LocStart.isInvalid()) assert(false && "Invalid SourceLocation"); // FIXME: handle forward protocol that are declared across multiple lines. - ReplaceText(LocStart, 0, "// ", 3); + ReplaceText(LocStart, 0, "// "); } void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD, @@ -1050,10 +1054,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID); ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID); - if (IMD) - InsertText(IMD->getLocStart(), "// ", 3); - else - InsertText(CID->getLocStart(), "// ", 3); + InsertText(IMD ? IMD->getLocStart() : CID->getLocStart(), "// "); for (ObjCCategoryImplDecl::instmeth_iterator I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), @@ -1067,8 +1068,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); - ReplaceText(LocStart, endBuf-startBuf, - ResultStr.c_str(), ResultStr.size()); + ReplaceText(LocStart, endBuf-startBuf, ResultStr); } for (ObjCCategoryImplDecl::classmeth_iterator @@ -1083,8 +1083,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); - ReplaceText(LocStart, endBuf-startBuf, - ResultStr.c_str(), ResultStr.size()); + ReplaceText(LocStart, endBuf-startBuf, ResultStr); } for (ObjCCategoryImplDecl::propimpl_iterator I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), @@ -1093,10 +1092,7 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { RewritePropertyImplDecl(*I, IMD, CID); } - if (IMD) - InsertText(IMD->getLocEnd(), "// ", 3); - else - InsertText(CID->getLocEnd(), "// ", 3); + InsertText(IMD ? IMD->getLocEnd() : CID->getLocEnd(), "// "); } void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { @@ -1130,7 +1126,7 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { RewriteMethodDeclaration(*I); // Lastly, comment out the @end. - ReplaceText(ClassDecl->getAtEndRange().getBegin(), 0, "// ", 3); + ReplaceText(ClassDecl->getAtEndRange().getBegin(), 0, "// "); } Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, @@ -1149,7 +1145,7 @@ Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt, // This allows us to handle chain/nested property getters. Receiver = PropGetters[PRE]; } - MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver), + MsgExpr = new (Context) ObjCMessageExpr(*Context, dyn_cast<Expr>(Receiver), PDecl->getSetterName(), PDecl->getType(), PDecl->getSetterMethodDecl(), SourceLocation(), SourceLocation(), @@ -1178,7 +1174,7 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { // This allows us to handle chain/nested property getters. Receiver = PropGetters[PRE]; } - MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver), + MsgExpr = new (Context) ObjCMessageExpr(*Context, dyn_cast<Expr>(Receiver), PDecl->getGetterName(), PDecl->getType(), PDecl->getGetterMethodDecl(), SourceLocation(), SourceLocation(), @@ -1209,14 +1205,15 @@ Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) { } Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, - SourceLocation OrigStart) { + SourceLocation OrigStart, + bool &replaced) { ObjCIvarDecl *D = IV->getDecl(); const Expr *BaseExpr = IV->getBase(); if (CurMethodDef) { - if (BaseExpr->getType()->isObjCObjectPointerType() && - isa<DeclRefExpr>(BaseExpr)) { + if (BaseExpr->getType()->isObjCObjectPointerType()) { 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(), @@ -1226,7 +1223,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // Synthesize an explicit cast to gain access to the ivar. std::string RecName = clsDeclared->getIdentifier()->getName(); RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName.c_str()); + IdentifierInfo *II = &Context->Idents.get(RecName); RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, SourceLocation(), II); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); @@ -1238,17 +1235,16 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, 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()); - ReplaceStmt(IV, ME); // delete IV; leak for now, see RewritePropertySetter() usage for more info. return ME; } - - ReplaceStmt(IV->getBase(), PE); + // 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]. @@ -1272,7 +1268,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // Synthesize an explicit cast to gain access to the ivar. std::string RecName = clsDeclared->getIdentifier()->getName(); RecName += "_IMPL"; - IdentifierInfo *II = &Context->Idents.get(RecName.c_str()); + IdentifierInfo *II = &Context->Idents.get(RecName); RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, SourceLocation(), II); assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl"); @@ -1283,7 +1279,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, // Don't forget the parens to enforce the proper binding. ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(), IV->getBase()->getLocEnd(), castExpr); - ReplaceStmt(IV->getBase(), PE); + 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]. @@ -1294,6 +1290,28 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, return IV; } +Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) { + for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); + CI != E; ++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; + } + return S; +} + /// SynthCountByEnumWithState - To print: /// ((unsigned int (*) /// (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int)) @@ -1326,7 +1344,7 @@ Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) { SourceLocation startLoc = S->getLocStart(); buf = "goto __break_label_"; buf += utostr(ObjCBcLabelNo.back()); - ReplaceText(startLoc, strlen("break"), buf.c_str(), buf.size()); + ReplaceText(startLoc, strlen("break"), buf); return 0; } @@ -1343,7 +1361,7 @@ Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) { SourceLocation startLoc = S->getLocStart(); buf = "goto __continue_label_"; buf += utostr(ObjCBcLabelNo.back()); - ReplaceText(startLoc, strlen("continue"), buf.c_str(), buf.size()); + ReplaceText(startLoc, strlen("continue"), buf); return 0; } @@ -1442,8 +1460,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, startCollectionBuf += 3; // Replace: "for (type element in" with string constructed thus far. - ReplaceText(startLoc, startCollectionBuf - startBuf, - buf.c_str(), buf.size()); + ReplaceText(startLoc, startCollectionBuf - startBuf, buf); // Replace ')' in for '(' type elem in collection ')' with ';' SourceLocation rightParenLoc = S->getRParenLoc(); const char *rparenBuf = SM->getCharacterData(rightParenLoc); @@ -1484,7 +1501,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, buf += elementTypeAsString; buf += ")enumState.itemsPtr[counter++];"; // Replace ')' in for '(' type elem in collection ')' with all of these. - ReplaceText(lparenLoc, 1, buf.c_str(), buf.size()); + ReplaceText(lparenLoc, 1, buf); /// __continue_label: ; /// } while (counter < limit); @@ -1525,7 +1542,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, // FIXME: If this should support Obj-C++, support CXXTryStmt if (isa<CompoundStmt>(S->getBody())) { SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1); - InsertText(endBodyLoc, buf.c_str(), buf.size()); + InsertText(endBodyLoc, buf); } else { /* Need to treat single statements specially. For example: * @@ -1538,7 +1555,7 @@ Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S, const char *semiBuf = strchr(stmtBuf, ';'); assert(semiBuf && "Can't find ';'"); SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(semiBuf-stmtBuf+1); - InsertText(endBodyLoc, buf.c_str(), buf.size()); + InsertText(endBodyLoc, buf); } Stmts.pop_back(); ObjCBcLabelNo.pop_back(); @@ -1562,7 +1579,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { buf = "objc_sync_enter((id)"; const char *lparenBuf = startBuf; while (*lparenBuf != '(') lparenBuf++; - ReplaceText(startLoc, lparenBuf-startBuf+1, buf.c_str(), buf.size()); + ReplaceText(startLoc, lparenBuf-startBuf+1, buf); // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since // the sync expression is typically a message expression that's already // been rewritten! (which implies the SourceLocation's are invalid). @@ -1578,7 +1595,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { buf += "id volatile _rethrow = 0;\n"; buf += "objc_exception_try_enter(&_stack);\n"; buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; - ReplaceText(rparenLoc, 1, buf.c_str(), buf.size()); + ReplaceText(rparenLoc, 1, buf); startLoc = S->getSynchBody()->getLocEnd(); startBuf = SM->getCharacterData(startLoc); @@ -1607,7 +1624,7 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { buf += "}\n"; buf += "}"; - ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); + ReplaceText(lastCurlyLoc, 1, buf); bool hasReturns = false; HasReturnStmts(S->getSynchBody(), hasReturns); @@ -1663,8 +1680,8 @@ void RewriteObjC::RewriteTryReturnStmts(Stmt *S) { std::string buf; buf = "{ objc_exception_try_exit(&_stack); return"; - ReplaceText(startLoc, 6, buf.c_str(), buf.size()); - InsertText(onePastSemiLoc, "}", 1); + ReplaceText(startLoc, 6, buf); + InsertText(onePastSemiLoc, "}"); } return; } @@ -1689,8 +1706,8 @@ void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) { buf += syncExitBuf; buf += " return"; - ReplaceText(startLoc, 6, buf.c_str(), buf.size()); - InsertText(onePastSemiLoc, "}", 1); + ReplaceText(startLoc, 6, buf); + InsertText(onePastSemiLoc, "}"); } return; } @@ -1711,7 +1728,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += "objc_exception_try_enter(&_stack);\n"; buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n"; - ReplaceText(startLoc, 4, buf.c_str(), buf.size()); + ReplaceText(startLoc, 4, buf); startLoc = S->getTryBody()->getLocEnd(); startBuf = SM->getCharacterData(startLoc); @@ -1729,12 +1746,12 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += " _rethrow = objc_exception_extract(&_stack);\n"; buf += " else { /* @catch continue */"; - InsertText(startLoc, buf.c_str(), buf.size()); + InsertText(startLoc, buf); } else { /* no catch list */ buf = "}\nelse {\n"; buf += " _rethrow = objc_exception_extract(&_stack);\n"; buf += "}"; - ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); + ReplaceText(lastCurlyLoc, 1, buf); } bool sawIdTypedCatch = false; Stmt *lastCatchBody = 0; @@ -1767,7 +1784,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { QualType t = catchDecl->getType(); if (t == Context->getObjCIdType()) { buf += "1) { "; - ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size()); + ReplaceText(startLoc, lParenLoc-startBuf+1, buf); sawIdTypedCatch = true; } else if (t->isObjCObjectPointerType()) { QualType InterfaceTy = t->getPointeeType(); @@ -1777,7 +1794,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += "objc_exception_match((struct objc_class *)objc_getClass(\""; buf += cls->getDecl()->getNameAsString(); buf += "\"), (struct objc_object *)_caught)) { "; - ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size()); + ReplaceText(startLoc, lParenLoc-startBuf+1, buf); } } // Now rewrite the body... @@ -1789,10 +1806,9 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { assert((*rParenBuf == ')') && "bogus @catch paren location"); assert((*bodyBuf == '{') && "bogus @catch body location"); - buf = " = _caught;"; // Here we replace ") {" with "= _caught;" (which initializes and // declares the @catch parameter). - ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, buf.c_str(), buf.size()); + ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, " = _caught;"); } else { assert(false && "@catch rewrite bug"); } @@ -1814,7 +1830,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += "} } /* @catch end */\n"; if (!S->getFinallyStmt()) buf += "}\n"; - InsertText(bodyLoc, buf.c_str(), buf.size()); + InsertText(bodyLoc, buf); // Set lastCurlyLoc lastCurlyLoc = lastCatchBody->getLocEnd(); @@ -1824,8 +1840,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { startBuf = SM->getCharacterData(startLoc); assert((*startBuf == '@') && "bogus @finally start"); - buf = "/* @finally */"; - ReplaceText(startLoc, 8, buf.c_str(), buf.size()); + ReplaceText(startLoc, 8, "/* @finally */"); Stmt *body = finalStmt->getFinallyBody(); SourceLocation startLoc = body->getLocStart(); @@ -1836,11 +1851,9 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { "bogus @finally body location"); startLoc = startLoc.getFileLocWithOffset(1); - buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; - InsertText(startLoc, buf.c_str(), buf.size()); + InsertText(startLoc, " if (!_rethrow) objc_exception_try_exit(&_stack);\n"); endLoc = endLoc.getFileLocWithOffset(-1); - buf = " if (_rethrow) objc_exception_throw(_rethrow);\n"; - InsertText(endLoc, buf.c_str(), buf.size()); + InsertText(endLoc, " if (_rethrow) objc_exception_throw(_rethrow);\n"); // Set lastCurlyLoc lastCurlyLoc = body->getLocEnd(); @@ -1852,7 +1865,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n"; buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; buf += "}"; - ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size()); + ReplaceText(lastCurlyLoc, 1, buf); // Now check for any return/continue/go statements within the @try. // The implicit finally clause won't called if the @try contains any @@ -1864,8 +1877,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) { } // Now emit the final closing curly brace... lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1); - buf = " } /* @try scope end */\n"; - InsertText(lastCurlyLoc, buf.c_str(), buf.size()); + InsertText(lastCurlyLoc, " } /* @try scope end */\n"); return 0; } @@ -1897,13 +1909,12 @@ Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) { // handle "@ throw" correctly. const char *wBuf = strchr(startBuf, 'w'); assert((*wBuf == 'w') && "@throw: can't find 'w'"); - ReplaceText(startLoc, wBuf-startBuf+1, buf.c_str(), buf.size()); + ReplaceText(startLoc, wBuf-startBuf+1, buf); const char *semiBuf = strchr(startBuf, ';'); assert((*semiBuf == ';') && "@throw: can't find ';'"); SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf); - buf = ");"; - ReplaceText(semiLoc, 1, buf.c_str(), buf.size()); + ReplaceText(semiLoc, 1, ");"); return 0; } @@ -1991,7 +2002,17 @@ static void scanToNextArgument(const char *&argRef) { } bool RewriteObjC::needToScanForQualifiers(QualType T) { - return T->isObjCQualifiedIdType() || T->isObjCQualifiedInterfaceType(); + if (T->isObjCQualifiedIdType()) + return true; + if (const PointerType *PT = T->getAs<PointerType>()) { + if (PT->getPointeeType()->isObjCQualifiedIdType()) + return true; + } + if (T->isObjCObjectPointerType()) { + T = T->getPointeeType(); + return T->isObjCQualifiedInterfaceType(); + } + return false; } void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { @@ -2018,8 +2039,8 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) { SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf); SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1); // Comment out the protocol references. - InsertText(LessLoc, "/*", 2); - InsertText(GreaterLoc, "*/", 2); + InsertText(LessLoc, "/*"); + InsertText(GreaterLoc, "*/"); } } } @@ -2063,8 +2084,8 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf); SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1); // Comment out the protocol references. - InsertText(LessLoc, "/*", 2); - InsertText(GreaterLoc, "*/", 2); + InsertText(LessLoc, "/*"); + InsertText(GreaterLoc, "*/"); } } if (!proto) @@ -2087,8 +2108,8 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startFuncBuf+1); // Comment out the protocol references. - InsertText(LessLoc, "/*", 2); - InsertText(GreaterLoc, "*/", 2); + InsertText(LessLoc, "/*"); + InsertText(GreaterLoc, "*/"); } startBuf = ++endBuf; } @@ -2102,6 +2123,42 @@ void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) { } } +void RewriteObjC::RewriteTypeOfDecl(VarDecl *ND) { + QualType QT = ND->getType(); + const Type* TypePtr = QT->getAs<Type>(); + if (!isa<TypeOfExprType>(TypePtr)) + return; + while (isa<TypeOfExprType>(TypePtr)) { + const TypeOfExprType *TypeOfExprTypePtr = cast<TypeOfExprType>(TypePtr); + QT = TypeOfExprTypePtr->getUnderlyingExpr()->getType(); + TypePtr = QT->getAs<Type>(); + } + // FIXME. This will not work for multiple declarators; as in: + // __typeof__(a) b,c,d; + std::string TypeAsString(QT.getAsString()); + SourceLocation DeclLoc = ND->getTypeSpecStartLoc(); + const char *startBuf = SM->getCharacterData(DeclLoc); + if (ND->getInit()) { + std::string Name(ND->getNameAsString()); + TypeAsString += " " + Name + " = "; + Expr *E = ND->getInit(); + SourceLocation startLoc; + if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) + startLoc = ECE->getLParenLoc(); + else + startLoc = E->getLocStart(); + startLoc = SM->getInstantiationLoc(startLoc); + const char *endBuf = SM->getCharacterData(startLoc); + ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); + } + else { + SourceLocation X = ND->getLocEnd(); + X = SM->getInstantiationLoc(X); + const char *endBuf = SM->getCharacterData(X); + ReplaceText(DeclLoc, endBuf-startBuf-1, TypeAsString); + } +} + // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str); void RewriteObjC::SynthSelGetUidFunctionDecl() { IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName"); @@ -2126,6 +2183,19 @@ void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) { RewriteObjCQualifiedInterfaceTypes(FD); } +static void RewriteBlockPointerType(std::string& Str, QualType Type) { + std::string TypeString(Type.getAsString()); + const char *argPtr = TypeString.c_str(); + if (!strchr(argPtr, '^')) { + Str += TypeString; + return; + } + while (*argPtr) { + Str += (*argPtr == '^' ? '*' : *argPtr); + argPtr++; + } +} + void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { SourceLocation FunLocStart = FD->getTypeSpecStartLoc(); const FunctionType *funcType = FD->getType()->getAs<FunctionType>(); @@ -2140,13 +2210,12 @@ void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) { unsigned numArgs = proto->getNumArgs(); for (unsigned i = 0; i < numArgs; i++) { QualType ArgType = proto->getArgType(i); - FdStr += ArgType.getAsString(); - + RewriteBlockPointerType(FdStr, ArgType); if (i+1 < numArgs) FdStr += ", "; } FdStr += ");\n"; - InsertText(FunLocStart, FdStr.c_str(), FdStr.size()); + InsertText(FunLocStart, FdStr); CurFunctionDeclToDeclareForBlock = 0; } @@ -2330,7 +2399,7 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { Preamble += utostr(Exp->getString()->getByteLength()) + "};\n"; VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(), - &Context->Idents.get(S.c_str()), strType, 0, + &Context->Idents.get(S), strType, 0, VarDecl::Static); DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation()); Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf, @@ -2380,7 +2449,7 @@ QualType RewriteObjC::getSuperStructType() { /*Mutable=*/false)); } - SuperStructDecl->completeDefinition(*Context); + SuperStructDecl->completeDefinition(); } return Context->getTagDeclType(SuperStructDecl); } @@ -2411,7 +2480,7 @@ QualType RewriteObjC::getConstantStringStructType() { /*Mutable=*/true)); } - ConstantStringDecl->completeDefinition(*Context); + ConstantStringDecl->completeDefinition(); } return Context->getTagDeclType(ConstantStringDecl); } @@ -2871,7 +2940,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, if ((CDecl->isForwardDecl() || NumIvars == 0) && (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) { endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); - ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size()); + ReplaceText(LocStart, endBuf-startBuf, Result); return; } @@ -2913,10 +2982,10 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, endHeader++; } // rewrite the original header - ReplaceText(LocStart, endHeader-startBuf, Result.c_str(), Result.size()); + ReplaceText(LocStart, endHeader-startBuf, Result); } else { // rewrite the original header *without* disturbing the '{' - ReplaceText(LocStart, cursor-startBuf, Result.c_str(), Result.size()); + ReplaceText(LocStart, cursor-startBuf, Result); } if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) { Result = "\n struct "; @@ -2928,7 +2997,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, // insert the super class structure definition. SourceLocation OnePastCurly = LocStart.getFileLocWithOffset(cursor-startBuf+1); - InsertText(OnePastCurly, Result.c_str(), Result.size()); + InsertText(OnePastCurly, Result); } cursor++; // past '{' @@ -2946,26 +3015,26 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, !strncmp(cursor, "private", strlen("private")) || !strncmp(cursor, "package", strlen("package")) || !strncmp(cursor, "protected", strlen("protected"))) - InsertText(atLoc, "// ", 3); + InsertText(atLoc, "// "); } // FIXME: If there are cases where '<' is used in ivar declaration part // of user code, then scan the ivar list and use needToScanForQualifiers // for type checking. else if (*cursor == '<') { SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); - InsertText(atLoc, "/* ", 3); + InsertText(atLoc, "/* "); cursor = strchr(cursor, '>'); cursor++; atLoc = LocStart.getFileLocWithOffset(cursor-startBuf); - InsertText(atLoc, " */", 3); + InsertText(atLoc, " */"); } else if (*cursor == '^') { // rewrite block specifier. SourceLocation caretLoc = LocStart.getFileLocWithOffset(cursor-startBuf); - ReplaceText(caretLoc, 1, "*", 1); + ReplaceText(caretLoc, 1, "*"); } cursor++; } // Don't forget to add a ';'!! - InsertText(LocEnd.getFileLocWithOffset(1), ";", 1); + InsertText(LocEnd.getFileLocWithOffset(1), ";"); } else { // we don't have any instance variables - insert super struct. endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts); Result += " {\n struct "; @@ -2973,7 +3042,7 @@ void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl, Result += "_IMPL "; Result += RCDecl->getNameAsString(); Result += "_IVARS;\n};\n"; - ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size()); + ReplaceText(LocStart, endBuf-startBuf, Result); } // Mark this struct as having been generated. if (!ObjCSynthesizedStructs.insert(CDecl)) @@ -3805,7 +3874,7 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, // Create local declarations to avoid rewriting all closure decl ref exprs. // First, emit a declaration for all "by ref" decls. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); @@ -3816,7 +3885,7 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i, S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n"; } // Next, emit a declaration for all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { S += " "; std::string Name = (*I)->getNameAsString(); @@ -3861,7 +3930,7 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, S += (*I)->getNameAsString(); S += ", (void*)src->"; S += (*I)->getNameAsString(); - if (BlockByRefDecls.count((*I))) + if (BlockByRefDeclsPtrSet.count((*I))) S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; else S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; @@ -3877,7 +3946,7 @@ std::string RewriteObjC::SynthesizeBlockHelperFuncs(BlockExpr *CE, int i, E = ImportedBlockDecls.end(); I != E; ++I) { S += "_Block_object_dispose((void*)src->"; S += (*I)->getNameAsString(); - if (BlockByRefDecls.count((*I))) + if (BlockByRefDeclsPtrSet.count((*I))) S += ", " + utostr(BLOCK_FIELD_IS_BYREF) + "/*BLOCK_FIELD_IS_BYREF*/);"; else S += ", " + utostr(BLOCK_FIELD_IS_OBJECT) + "/*BLOCK_FIELD_IS_OBJECT*/);"; @@ -3901,7 +3970,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, if (BlockDeclRefs.size()) { // Output all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { S += " "; std::string FieldName = (*I)->getNameAsString(); @@ -3927,7 +3996,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, S += FieldName + ";\n"; } // Output all "by ref" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { S += " "; std::string FieldName = (*I)->getNameAsString(); @@ -3966,7 +4035,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, Constructor += " Desc = desc;\n"; // Initialize all "by copy" arguments. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { std::string Name = (*I)->getNameAsString(); Constructor += " "; @@ -3977,7 +4046,7 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag, Constructor += Name + ";\n"; } // Initialize all "by ref" arguments. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { std::string Name = (*I)->getNameAsString(); Constructor += " "; @@ -4047,23 +4116,25 @@ void RewriteObjC::SynthesizeBlockLiterals(SourceLocation FunLocStart, std::string CI = SynthesizeBlockImpl(Blocks[i], ImplTag, DescTag); - InsertText(FunLocStart, CI.c_str(), CI.size()); + InsertText(FunLocStart, CI); std::string CF = SynthesizeBlockFunc(Blocks[i], i, FunName, ImplTag); - InsertText(FunLocStart, CF.c_str(), CF.size()); + InsertText(FunLocStart, CF); if (ImportedBlockDecls.size()) { std::string HF = SynthesizeBlockHelperFuncs(Blocks[i], i, FunName, ImplTag); - InsertText(FunLocStart, HF.c_str(), HF.size()); + InsertText(FunLocStart, HF); } std::string BD = SynthesizeBlockDescriptor(DescTag, ImplTag, i, FunName, ImportedBlockDecls.size() > 0); - InsertText(FunLocStart, BD.c_str(), BD.size()); + InsertText(FunLocStart, BD); BlockDeclRefs.clear(); BlockByRefDecls.clear(); + BlockByRefDeclsPtrSet.clear(); BlockByCopyDecls.clear(); + BlockByCopyDeclsPtrSet.clear(); BlockCallExprs.clear(); ImportedBlockDecls.clear(); } @@ -4078,17 +4149,23 @@ void RewriteObjC::InsertBlockLiteralsWithinFunction(FunctionDecl *FD) { SynthesizeBlockLiterals(FunLocStart, FuncName); } -void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { - //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); - //SourceLocation FunLocStart = MD->getLocStart(); - // FIXME: This hack works around a bug in Rewrite.InsertText(). - SourceLocation FunLocStart = MD->getLocStart().getFileLocWithOffset(-1); - std::string FuncName = MD->getSelector().getAsString(); +static void BuildUniqueMethodName(std::string &Name, + ObjCMethodDecl *MD) { + ObjCInterfaceDecl *IFace = MD->getClassInterface(); + Name = IFace->getNameAsCString(); + Name += "__" + MD->getSelector().getAsString(); // Convert colons to underscores. std::string::size_type loc = 0; - while ((loc = FuncName.find(":", loc)) != std::string::npos) - FuncName.replace(loc, 1, "_"); + while ((loc = Name.find(":", loc)) != std::string::npos) + Name.replace(loc, 1, "_"); +} +void RewriteObjC::InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD) { + //fprintf(stderr,"In InsertBlockLiteralsWitinMethod\n"); + //SourceLocation FunLocStart = MD->getLocStart(); + SourceLocation FunLocStart = MD->getLocStart(); + std::string FuncName; + BuildUniqueMethodName(FuncName, MD); SynthesizeBlockLiterals(FunLocStart, FuncName.c_str()); } @@ -4304,11 +4381,9 @@ void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { std::string TypeAsString = "("; TypeAsString += QT.getAsString(); TypeAsString += ")"; - ReplaceText(LocStart, endBuf-startBuf+1, - TypeAsString.c_str(), TypeAsString.size()); + ReplaceText(LocStart, endBuf-startBuf+1, TypeAsString); return; } - // advance the location to startArgList. const char *argPtr = startBuf; @@ -4317,7 +4392,7 @@ void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) { case '^': // Replace the '^' with '*'. LocStart = LocStart.getFileLocWithOffset(argPtr-startBuf); - ReplaceText(LocStart, 1, "*", 1); + ReplaceText(LocStart, 1, "*"); break; } } @@ -4346,7 +4421,7 @@ void RewriteObjC::RewriteBlockPointerFunctionArgs(FunctionDecl *FD) { case '^': // Replace the '^' with '*'. DeclLoc = DeclLoc.getFileLocWithOffset(argPtr-startArgList); - ReplaceText(DeclLoc, 1, "*", 1); + ReplaceText(DeclLoc, 1, "*"); break; case '(': parenCount++; @@ -4427,7 +4502,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { if (*startBuf == '^') { // Replace the '^' with '*', computing a negative offset. DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf); - ReplaceText(DeclLoc, 1, "*", 1); + ReplaceText(DeclLoc, 1, "*"); } if (PointerTypeTakesAnyBlockArguments(DeclT)) { // Replace the '^' with '*' for arguments. @@ -4438,7 +4513,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { while (argListBegin < argListEnd) { if (*argListBegin == '^') { SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf); - ReplaceText(CaretLoc, 1, "*", 1); + ReplaceText(CaretLoc, 1, "*"); } argListBegin++; } @@ -4563,7 +4638,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { assert(CurMethodDef && "RewriteByRefVar - CurMethodDef is null"); FunLocStart = CurMethodDef->getLocStart(); } - InsertText(FunLocStart, ByrefType.c_str(), ByrefType.size()); + InsertText(FunLocStart, ByrefType); if (Ty.isObjCGCWeak()) { flag |= BLOCK_FIELD_IS_WEAK; isa = 1; @@ -4579,7 +4654,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { flag |= BLOCK_FIELD_IS_OBJECT; std::string HF = SynthesizeByrefCopyDestroyHelper(ND, flag); if (!HF.empty()) - InsertText(FunLocStart, HF.c_str(), HF.size()); + InsertText(FunLocStart, HF); } // struct __Block_byref_ND ND = @@ -4592,10 +4667,12 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { Name = ND->getNameAsString(); ByrefType.clear(); RewriteByRefString(ByrefType, Name, ND); + std::string ForwardingCastType("("); + ForwardingCastType += ByrefType + " *)"; if (!hasInit) { ByrefType += " " + Name + " = {(void*)"; ByrefType += utostr(isa); - ByrefType += ", &" + Name + ", "; + ByrefType += "," + ForwardingCastType + "&" + Name + ", "; ByrefType += utostr(flags); ByrefType += ", "; ByrefType += "sizeof("; @@ -4608,8 +4685,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { ByrefType += utostr(flag); } ByrefType += "};\n"; - ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), - ByrefType.c_str(), ByrefType.size()); + ReplaceText(DeclLoc, endBuf-startBuf+Name.size(), ByrefType); } else { SourceLocation startLoc; @@ -4624,7 +4700,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { ByrefType += " " + Name; ByrefType += " = {(void*)"; ByrefType += utostr(isa); - ByrefType += ", &" + Name + ", "; + ByrefType += "," + ForwardingCastType + "&" + Name + ", "; ByrefType += utostr(flags); ByrefType += ", "; ByrefType += "sizeof("; @@ -4637,8 +4713,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { ByrefType += utostr(flag); ByrefType += ", "; } - ReplaceText(DeclLoc, endBuf-startBuf, - ByrefType.c_str(), ByrefType.size()); + ReplaceText(DeclLoc, endBuf-startBuf, ByrefType); // Complete the newly synthesized compound expression by inserting a right // curly brace before the end of the declaration. @@ -4654,7 +4729,7 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) { SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf); - InsertText(semiLoc, "}", 1); + InsertText(semiLoc, "}"); } return; } @@ -4665,12 +4740,19 @@ 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()) - BlockByCopyDecls.insert(BlockDeclRefs[i]->getDecl()); + if (!BlockDeclRefs[i]->isByRef()) { + if (!BlockByCopyDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { + BlockByCopyDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); + BlockByCopyDecls.push_back(BlockDeclRefs[i]->getDecl()); + } + } // Unique all "by ref" declarations. for (unsigned i = 0; i < BlockDeclRefs.size(); i++) if (BlockDeclRefs[i]->isByRef()) { - BlockByRefDecls.insert(BlockDeclRefs[i]->getDecl()); + if (!BlockByRefDeclsPtrSet.count(BlockDeclRefs[i]->getDecl())) { + BlockByRefDeclsPtrSet.insert(BlockDeclRefs[i]->getDecl()); + BlockByRefDecls.push_back(BlockDeclRefs[i]->getDecl()); + } } // Find any imported blocks...they will need special attention. for (unsigned i = 0; i < BlockDeclRefs.size(); i++) @@ -4699,13 +4781,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { if (CurFunctionDef) FuncName = CurFunctionDef->getNameAsString(); - else if (CurMethodDef) { - FuncName = CurMethodDef->getSelector().getAsString(); - // Convert colons to underscores. - std::string::size_type loc = 0; - while ((loc = FuncName.find(":", loc)) != std::string::npos) - FuncName.replace(loc, 1, "_"); - } else if (GlobalVarDecl) + else if (CurMethodDef) + BuildUniqueMethodName(FuncName, CurMethodDef); + else if (GlobalVarDecl) FuncName = std::string(GlobalVarDecl->getNameAsString()); std::string BlockNumber = utostr(Blocks.size()-1); @@ -4752,7 +4830,7 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { if (BlockDeclRefs.size()) { Expr *Exp; // Output all "by copy" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByCopyDecls.begin(), E = BlockByCopyDecls.end(); I != E; ++I) { if (isObjCType((*I)->getType())) { // FIXME: Conform to ABI ([[obj retain] autorelease]). @@ -4770,13 +4848,25 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { InitExprs.push_back(Exp); } // Output all "by ref" declarations. - for (llvm::SmallPtrSet<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), + for (llvm::SmallVector<ValueDecl*,8>::iterator I = BlockByRefDecls.begin(), E = BlockByRefDecls.end(); I != E; ++I) { + ValueDecl *ND = (*I); + std::string Name(ND->getNameAsString()); + std::string RecName; + RewriteByRefString(RecName, Name, ND); + IdentifierInfo *II = &Context->Idents.get(RecName.c_str() + + sizeof("struct")); + RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl, + SourceLocation(), II); + assert(RD && "SynthBlockInitExpr(): Can't find RecordDecl"); + QualType castT = Context->getPointerType(Context->getTagDeclType(RD)); + FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString()); Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation()); Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, Context->getPointerType(Exp->getType()), SourceLocation()); + Exp = NoTypeInfoCStyleCastExpr(Context, castT, CastExpr::CK_Unknown, Exp); InitExprs.push_back(Exp); } } @@ -4798,7 +4888,9 @@ Stmt *RewriteObjC::SynthBlockInitExpr(BlockExpr *Exp) { NewRep); BlockDeclRefs.clear(); BlockByRefDecls.clear(); + BlockByRefDeclsPtrSet.clear(); BlockByCopyDecls.clear(); + BlockByCopyDeclsPtrSet.clear(); ImportedBlockDecls.clear(); return NewRep; } @@ -4843,7 +4935,21 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E; ++CI) if (*CI) { - Stmt *newStmt = RewriteFunctionBodyOrGlobalInitializer(*CI); + Stmt *newStmt; + Stmt *S = (*CI); + if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) { + Expr *OldBase = IvarRefExpr->getBase(); + bool replaced = false; + newStmt = RewriteObjCNestedIvarRefExpr(S, replaced); + if (replaced) { + if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(newStmt)) + ReplaceStmt(OldBase, IRE->getBase()); + else + ReplaceStmt(S, newStmt); + } + } + else + newStmt = RewriteFunctionBodyOrGlobalInitializer(S); if (newStmt) *CI = newStmt; } @@ -4865,9 +4971,6 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { if (ObjCEncodeExpr *AtEncode = dyn_cast<ObjCEncodeExpr>(S)) return RewriteAtEncode(AtEncode); - if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) - return RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin()); - if (ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(S)) { BinaryOperator *BinOp = PropSetters[PropRefExpr]; if (BinOp) { @@ -4995,7 +5098,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { RewriteBlockPointerDecl(ND); else if (ND->getType()->isFunctionPointerType()) CheckFunctionPointerDecl(ND->getType(), ND); - if (VarDecl *VD = dyn_cast<VarDecl>(SD)) + if (VarDecl *VD = dyn_cast<VarDecl>(SD)) { if (VD->hasAttr<BlocksAttr>()) { static unsigned uniqueByrefDeclCount = 0; assert(!BlockByRefDeclNo.count(ND) && @@ -5003,6 +5106,9 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { BlockByRefDeclNo[ND] = uniqueByrefDeclCount++; RewriteByRefVar(VD); } + else + RewriteTypeOfDecl(VD); + } } if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) @@ -5191,11 +5297,6 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { } void RewriteObjC::HandleTranslationUnit(ASTContext &C) { - // Get the top-level buffer that this corresponds to. - - // Rewrite tabs if we care. - //RewriteTabs(); - if (Diags.hasErrorOccurred()) return; @@ -5207,8 +5308,7 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) { E = ProtocolExprDecls.end(); I != E; ++I) RewriteObjCProtocolMetaData(*I, "", "", Preamble); - InsertText(SM->getLocForStartOfFile(MainFileID), - Preamble.c_str(), Preamble.size(), false); + InsertText(SM->getLocForStartOfFile(MainFileID), Preamble, false); if (ClassImplementation.size() || CategoryImplementation.size()) RewriteImplementations(); @@ -5219,7 +5319,7 @@ void RewriteObjC::HandleTranslationUnit(ASTContext &C) { //printf("Changed:\n"); *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end()); } else { - fprintf(stderr, "No changes\n"); + llvm::errs() << "No changes\n"; } if (ClassImplementation.size() || CategoryImplementation.size() || |