From a5e2b23b594a03a5ab846ec9433a720cb3f3cc3a Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Mon, 29 Aug 2011 22:21:46 +0000 Subject: [PATCH] Fix a rewriter bug caused by recent changes in objc's group decls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@138772 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Rewrite/RewriteObjC.cpp | 91 ++++++++++++++++++-------- test/Rewriter/rewrite-forward-class.mm | 44 +++++++++++++ 2 files changed, 109 insertions(+), 26 deletions(-) create mode 100644 test/Rewriter/rewrite-forward-class.mm diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index ba518069eb..645883606a 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/lib/Rewrite/RewriteObjC.cpp @@ -247,6 +247,10 @@ namespace { // Syntactic Rewriting. void RewriteInclude(); void RewriteForwardClassDecl(DeclGroupRef D); + void RewriteForwardClassDecl(const llvm::SmallVector &DG); + void RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, + const std::string &typedefString); + void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, ObjCImplementationDecl *IMD, ObjCCategoryImplDecl *CID); @@ -722,8 +726,23 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { // Recurse into linkage specifications for (DeclContext::decl_iterator DI = LSD->decls_begin(), DIEnd = LSD->decls_end(); - DI != DIEnd; ++DI) + DI != DIEnd; ) { + if (isa((*DI))) { + SmallVector DG; + Decl *D = (*DI); + SourceLocation Loc = D->getLocation(); + while (DI != DIEnd && + isa(D) && D->getLocation() == Loc) { + DG.push_back(D); + ++DI; + D = (*DI); + } + RewriteForwardClassDecl(DG); + continue; + } HandleTopLevelSingleDecl(*DI); + ++DI; + } } // If we have a decl in the main file, see if we should rewrite it. if (SM->isFromMainFile(Loc)) @@ -891,41 +910,61 @@ void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID, InsertText(onePastSemiLoc, Setr); } +static void RewriteOneForwardClassDecl(ObjCInterfaceDecl *ForwardDecl, + std::string &typedefString) { + typedefString += "#ifndef _REWRITER_typedef_"; + typedefString += ForwardDecl->getNameAsString(); + typedefString += "\n"; + typedefString += "#define _REWRITER_typedef_"; + typedefString += ForwardDecl->getNameAsString(); + typedefString += "\n"; + typedefString += "typedef struct objc_object "; + typedefString += ForwardDecl->getNameAsString(); + typedefString += ";\n#endif\n"; +} + +void RewriteObjC::RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, + const std::string &typedefString) { + SourceLocation startLoc = ClassDecl->getLocation(); + const char *startBuf = SM->getCharacterData(startLoc); + const char *semiPtr = strchr(startBuf, ';'); + // Replace the @class with typedefs corresponding to the classes. + ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); +} + void RewriteObjC::RewriteForwardClassDecl(DeclGroupRef D) { - SourceLocation startLoc; std::string typedefString; - const char *startBuf = 0; - const char *semiPtr = 0; for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I) { ObjCClassDecl *ClassDecl = cast(*I); ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl(); if (I == D.begin()) { - // Get the start location and compute the semi location. - startLoc = ClassDecl->getLocation(); - startBuf = SM->getCharacterData(startLoc); - semiPtr = strchr(startBuf, ';'); + // Translate to typedef's that forward reference structs with the same name + // as the class. As a convenience, we include the original declaration + // as a comment. typedefString += "// @class "; typedefString += ForwardDecl->getNameAsString(); typedefString += ";\n"; } - // Translate to typedef's that forward reference structs with the same name - // as the class. As a convenience, we include the original declaration - // as a comment. - - - typedefString += "#ifndef _REWRITER_typedef_"; - typedefString += ForwardDecl->getNameAsString(); - typedefString += "\n"; - typedefString += "#define _REWRITER_typedef_"; - typedefString += ForwardDecl->getNameAsString(); - typedefString += "\n"; - typedefString += "typedef struct objc_object "; - typedefString += ForwardDecl->getNameAsString(); - typedefString += ";\n#endif\n"; - } - - // Replace the @class with typedefs corresponding to the classes. - ReplaceText(startLoc, semiPtr-startBuf+1, typedefString); + RewriteOneForwardClassDecl(ForwardDecl, typedefString); + } + DeclGroupRef::iterator I = D.begin(); + RewriteForwardClassEpilogue(cast(*I), typedefString); +} + +void RewriteObjC::RewriteForwardClassDecl( + const llvm::SmallVector &D) { + std::string typedefString; + for (unsigned i = 0; i < D.size(); i++) { + ObjCClassDecl *ClassDecl = cast(D[i]); + ObjCInterfaceDecl *ForwardDecl = ClassDecl->getForwardInterfaceDecl(); + if (i == 0) { + typedefString += "// @class "; + typedefString += ForwardDecl->getNameAsString(); + typedefString += ";\n"; + } + RewriteOneForwardClassDecl(ForwardDecl, typedefString); + } + RewriteForwardClassEpilogue(cast(D[0]), typedefString); } void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) { diff --git a/test/Rewriter/rewrite-forward-class.mm b/test/Rewriter/rewrite-forward-class.mm new file mode 100644 index 0000000000..74c0508fc7 --- /dev/null +++ b/test/Rewriter/rewrite-forward-class.mm @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp +// RUN: %clang_cc1 -fsyntax-only -fblocks -Wno-address-of-temporary -D"id=void*" -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp + +extern "C" { +@class XX; +@class YY, ZZ, QQ; +@class ISyncClient, SMSession, ISyncManager, ISyncSession, SMDataclassInfo, SMClientInfo, + DMCConfiguration, DMCStatusEntry; + +@interface QQ + +@end + +@interface SMDataclassInfo : QQ +- (XX*) Meth; +- (DMCStatusEntry*)Meth2; +@end + +@implementation SMDataclassInfo +- (XX*) Meth { return 0; } +- (DMCStatusEntry*)Meth2 { return 0; } +@end + +@interface YY +{ + ISyncClient *p1; + ISyncSession *p2; +} +@property (copy) ISyncClient *p1; +@end + +@implementation YY +@synthesize p1; +@end + +extern "C" { +@class CCC; +@class Protocol, P , Q; +int I,J,K; +}; + +}; + + -- 2.40.0