[cfe-commits] r138772 - in /cfe/trunk: lib/Rewrite/RewriteObjC.cpp test/Rewriter/rewrite-forward-class.mm

Fariborz Jahanian fjahanian at apple.com
Mon Aug 29 15:21:46 PDT 2011


Author: fjahanian
Date: Mon Aug 29 17:21:46 2011
New Revision: 138772

URL: http://llvm.org/viewvc/llvm-project?rev=138772&view=rev
Log:
Fix a rewriter bug caused by recent changes in objc's 
group decls.

Added:
    cfe/trunk/test/Rewriter/rewrite-forward-class.mm
Modified:
    cfe/trunk/lib/Rewrite/RewriteObjC.cpp

Modified: cfe/trunk/lib/Rewrite/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Rewrite/RewriteObjC.cpp?rev=138772&r1=138771&r2=138772&view=diff
==============================================================================
--- cfe/trunk/lib/Rewrite/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Rewrite/RewriteObjC.cpp Mon Aug 29 17:21:46 2011
@@ -247,6 +247,10 @@
     // Syntactic Rewriting.
     void RewriteInclude();
     void RewriteForwardClassDecl(DeclGroupRef D);
+    void RewriteForwardClassDecl(const llvm::SmallVector<Decl*, 8> &DG);
+    void RewriteForwardClassEpilogue(ObjCClassDecl *ClassDecl, 
+                                     const std::string &typedefString);
+      
     void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
                                  ObjCImplementationDecl *IMD,
                                  ObjCCategoryImplDecl *CID);
@@ -722,8 +726,23 @@
     // Recurse into linkage specifications
     for (DeclContext::decl_iterator DI = LSD->decls_begin(),
                                  DIEnd = LSD->decls_end();
-         DI != DIEnd; ++DI)
+         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);
+        }
+        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 @@
   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<ObjCClassDecl>(*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";
+    RewriteOneForwardClassDecl(ForwardDecl, typedefString);
   }
+  DeclGroupRef::iterator I = D.begin();
+  RewriteForwardClassEpilogue(cast<ObjCClassDecl>(*I), typedefString);
+}
 
-  // Replace the @class with typedefs corresponding to the classes.
-  ReplaceText(startLoc, semiPtr-startBuf+1, 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();
+    if (i == 0) {
+      typedefString += "// @class ";
+      typedefString += ForwardDecl->getNameAsString();
+      typedefString += ";\n";
+    }
+    RewriteOneForwardClassDecl(ForwardDecl, typedefString);
+  }
+  RewriteForwardClassEpilogue(cast<ObjCClassDecl>(D[0]), typedefString);
 }
 
 void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {

Added: cfe/trunk/test/Rewriter/rewrite-forward-class.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-forward-class.mm?rev=138772&view=auto
==============================================================================
--- cfe/trunk/test/Rewriter/rewrite-forward-class.mm (added)
+++ cfe/trunk/test/Rewriter/rewrite-forward-class.mm Mon Aug 29 17:21:46 2011
@@ -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" {
+ at class XX;
+ at class YY, ZZ, QQ;
+ at class ISyncClient, SMSession, ISyncManager, ISyncSession, SMDataclassInfo, SMClientInfo,
+    DMCConfiguration, DMCStatusEntry;
+
+ at interface QQ
+
+ at end
+
+ at interface SMDataclassInfo : QQ
+- (XX*) Meth;
+- (DMCStatusEntry*)Meth2;
+ at end
+
+ at implementation SMDataclassInfo
+- (XX*) Meth { return 0; }
+- (DMCStatusEntry*)Meth2 { return 0; }
+ at end
+
+ at interface YY 
+{
+  ISyncClient *p1;
+  ISyncSession *p2;
+}
+ at property (copy) ISyncClient *p1;
+ at end
+
+ at implementation YY
+ at synthesize p1;
+ at end
+
+extern "C" {
+ at class CCC;
+ at class Protocol, P , Q;
+int I,J,K;
+};
+
+};
+
+





More information about the cfe-commits mailing list