[cfe-commits] r51815 - /cfe/trunk/Driver/RewriteObjC.cpp

Steve Naroff snaroff at apple.com
Sat May 31 07:15:04 PDT 2008


Author: snaroff
Date: Sat May 31 09:15:04 2008
New Revision: 51815

URL: http://llvm.org/viewvc/llvm-project?rev=51815&view=rev
Log:
Fix <rdar://problem/5917992> clang ObjC rewriter: #end from #if statement lost in translation.

Some fancy footwork to accommodate embedded preprocessor directives within an interface.

Modified:
    cfe/trunk/Driver/RewriteObjC.cpp

Modified: cfe/trunk/Driver/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteObjC.cpp?rev=51815&r1=51814&r2=51815&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteObjC.cpp (original)
+++ cfe/trunk/Driver/RewriteObjC.cpp Sat May 31 09:15:04 2008
@@ -161,6 +161,7 @@
     ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr);
     QualType getSuperStructType();
     QualType getConstantStringStructType();
+    bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
     
     // Expression Rewriting.
     Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
@@ -2247,6 +2248,32 @@
   
 }
 
+bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf, 
+                                             const char *endBuf) {
+  while (startBuf < endBuf) {
+    if (*startBuf == '#') {
+      // Skip whitespace.
+      for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
+        ;
+      if (!strncmp(startBuf, "if", strlen("if")) ||
+          !strncmp(startBuf, "ifdef", strlen("ifdef")) ||
+          !strncmp(startBuf, "ifndef", strlen("ifndef")) ||
+          !strncmp(startBuf, "define", strlen("define")) ||
+          !strncmp(startBuf, "undef", strlen("undef")) ||
+          !strncmp(startBuf, "else", strlen("else")) ||
+          !strncmp(startBuf, "elif", strlen("elif")) ||
+          !strncmp(startBuf, "endif", strlen("endif")) ||
+          !strncmp(startBuf, "pragma", strlen("pragma")) ||
+          !strncmp(startBuf, "include", strlen("include")) ||
+          !strncmp(startBuf, "import", strlen("import")) ||
+          !strncmp(startBuf, "include_next", strlen("include_next")))
+        return true;
+    }
+    startBuf++;
+  }
+  return false;
+}
+
 /// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to
 /// an objective-c class with ivars.
 void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
@@ -2263,6 +2290,7 @@
   
   const char *startBuf = SM->getCharacterData(LocStart);
   const char *endBuf = SM->getCharacterData(LocEnd);
+  
   // If no ivars and no root or if its root, directly or indirectly,
   // have no ivars (thus not synthesized) then no need to synthesize this class.
   if ((CDecl->isForwardDecl() || NumIvars == 0) &&
@@ -2283,9 +2311,38 @@
     const char *cursor = strchr(startBuf, '{');
     assert((cursor && endBuf) 
            && "SynthesizeObjCInternalStruct - malformed @interface");
-    
-    // rewrite the original header *without* disturbing the '{'
-    ReplaceText(LocStart, cursor-startBuf-1, Result.c_str(), Result.size());
+    // If the buffer contains preprocessor directives, we do more fine-grained
+    // rewrites. This is intended to fix code that looks like (which occurs in
+    // NSURL.h, for example):
+    //
+    // #ifdef XYZ
+    // @interface Foo : NSObject
+    // #else
+    // @interface FooBar : NSObject
+    // #endif
+    // {
+    //    int i;
+    // }
+    // @end
+    //
+    // This clause is segregated to avoid breaking the common case.
+    if (BufferContainsPPDirectives(startBuf, cursor)) {
+      SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() : 
+                                  CDecl->getClassLoc();
+      const char *endHeader = SM->getCharacterData(L);
+      endHeader += Lexer::MeasureTokenLength(L, *SM);
+
+      if (CDecl->getNumIntfRefProtocols()) {
+        // advance to the end of the referenced protocols.
+        while (endHeader < cursor && *endHeader != '>') endHeader++;
+        endHeader++;
+      }
+      // rewrite the original header
+      ReplaceText(LocStart, endHeader-startBuf, Result.c_str(), Result.size());
+    } else {
+      // rewrite the original header *without* disturbing the '{'
+      ReplaceText(LocStart, cursor-startBuf-1, Result.c_str(), Result.size());
+    }
     if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
       Result = "\n    struct ";
       Result += RCDecl->getName();





More information about the cfe-commits mailing list