[cfe-commits] r56499 - in /cfe/trunk: Driver/RewriteBlocks.cpp test/Rewriter/block-test.c

Steve Naroff snaroff at apple.com
Tue Sep 23 12:24:42 PDT 2008


Author: snaroff
Date: Tue Sep 23 14:24:41 2008
New Revision: 56499

URL: http://llvm.org/viewvc/llvm-project?rev=56499&view=rev
Log:
Teach block rewriter to replace '^' with '*' in VarDecls.

Since we don't have DeclGroup's and location information for types, there is some fancy footwork to do this fairly reliably.

O.K...it's a kludge. One day, we can use this as motivation to do this more gracefully:-)

Added:
    cfe/trunk/test/Rewriter/block-test.c
Modified:
    cfe/trunk/Driver/RewriteBlocks.cpp

Modified: cfe/trunk/Driver/RewriteBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/RewriteBlocks.cpp?rev=56499&r1=56498&r2=56499&view=diff

==============================================================================
--- cfe/trunk/Driver/RewriteBlocks.cpp (original)
+++ cfe/trunk/Driver/RewriteBlocks.cpp Tue Sep 23 14:24:41 2008
@@ -131,6 +131,9 @@
   void RewriteCategoryDecl(ObjCCategoryDecl *CatDecl);
   void RewriteProtocolDecl(ObjCProtocolDecl *PDecl);
   void RewriteMethodDecl(ObjCMethodDecl *MDecl);
+  
+  bool BlockPointerTypeTakesAnyBlockArguments(QualType QT);
+  void GetExtentOfArgList(const char *Name, char *&LParen, char *&RParen);
 };
   
 }
@@ -455,9 +458,9 @@
     }
     if (haveByRefDecls) {
       // Remove |...|.
-      const char *firstBarPtr = strchr(BodyStartBuf, '|');
-      const char *secondBarPtr = strchr(firstBarPtr+1, '|');
-      BodyBuf.replace(firstBarPtr-BodyStartBuf, secondBarPtr-firstBarPtr+1, "");
+      //const char *firstBarPtr = strchr(BodyStartBuf, '|');
+      //const char *secondBarPtr = strchr(firstBarPtr+1, '|');
+      //BodyBuf.replace(firstBarPtr-BodyStartBuf, secondBarPtr-firstBarPtr+1, "");
     } 
     S += "  ";
     S += BodyBuf;
@@ -809,6 +812,40 @@
   return;
 }
 
+bool RewriteBlocks::BlockPointerTypeTakesAnyBlockArguments(QualType QT) {
+  const BlockPointerType *BPT = QT->getAsBlockPointerType();
+  assert(BPT && "BlockPointerTypeTakeAnyBlockArguments(): not a block pointer type");
+  const FunctionTypeProto *FTP = BPT->getPointeeType()->getAsFunctionTypeProto();
+  if (FTP) {
+    for (FunctionTypeProto::arg_type_iterator I = FTP->arg_type_begin(), 
+         E = FTP->arg_type_end(); I != E; ++I)
+      if (isBlockPointerType(*I))
+        return true;
+  }
+  return false;
+}
+
+void RewriteBlocks::GetExtentOfArgList(const char *Name, 
+                                       char *&LParen, char *&RParen) {
+  char *argPtr = strchr(Name, '(');
+  assert((*argPtr == '(') && "Rewriter fuzzy parser confused");
+  
+  LParen = argPtr; // output the start.
+  argPtr++; // skip past the left paren.
+  unsigned parenCount = 1;
+  
+  while (*argPtr && parenCount) {
+    switch (*argPtr) {
+      case '(': parenCount++; break;
+      case ')': parenCount--; break;
+      default: break;
+    }
+    if (parenCount) argPtr++;
+  }
+  assert((*argPtr == ')') && "Rewriter fuzzy parser confused");
+  RParen = argPtr; // output the end
+}
+
 void RewriteBlocks::RewriteBlockPointerDecl(NamedDecl *ND) {
   SourceLocation DeclLoc = ND->getLocation();
   const char *startBuf, *endBuf;
@@ -820,6 +857,29 @@
     DeclLoc = VD->getLocation();
     startBuf = SM->getCharacterData(DeclLoc);
     endBuf = startBuf;
+    // scan backward (from the decl location) for the end of the previous decl.
+    while (*startBuf != '^' && *startBuf != ';' && startBuf != MainFileStart)
+      startBuf--;
+    assert((*startBuf == '^') && 
+           "RewriteBlockPointerDecl() scan error: no caret");
+    // Replace the '^' with '*', computing a negative offset.
+    DeclLoc = DeclLoc.getFileLocWithOffset(startBuf-endBuf);
+    ReplaceText(DeclLoc, 1, "*", 1);
+    
+    if (BlockPointerTypeTakesAnyBlockArguments(VD->getType())) {
+      // Replace the '^' with '*' for arguments.
+      DeclLoc = VD->getLocation();
+      startBuf = SM->getCharacterData(DeclLoc);
+      char *argListBegin, *argListEnd;
+      GetExtentOfArgList(startBuf, argListBegin, argListEnd);
+      while (argListBegin < argListEnd) {
+        if (*argListBegin == '^') {
+          SourceLocation CaretLoc = DeclLoc.getFileLocWithOffset(argListBegin-startBuf);
+          ReplaceText(CaretLoc, 1, "*", 1);
+        }
+        argListBegin++;
+      }
+    }
   } else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND)) {
     DeclLoc = TDD->getLocation();
     startBuf = SM->getCharacterData(DeclLoc);
@@ -828,15 +888,7 @@
       DeclLoc = DeclLoc.getFileLocWithOffset(8);
     }
     endBuf = startBuf;
-  }  
-  // FIXME: need to skip past the argument list...then check for ','.
-  while (*endBuf && *endBuf != '=' && *endBuf != ';')
-    endBuf++;
-  
-  SourceLocation DeclEndLoc = DeclLoc.getFileLocWithOffset(endBuf-startBuf);
-  
-  std::string Tag = "struct __closure_impl *" + std::string(ND->getName());
-  ReplaceText(DeclLoc, endBuf-startBuf, Tag.c_str(), Tag.size());
+  }
   return;
 }
 

Added: cfe/trunk/test/Rewriter/block-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/block-test.c?rev=56499&view=auto

==============================================================================
--- cfe/trunk/test/Rewriter/block-test.c (added)
+++ cfe/trunk/test/Rewriter/block-test.c Tue Sep 23 14:24:41 2008
@@ -0,0 +1,27 @@
+// RUN: clang -rewrite-blocks %s -o -
+
+typedef void (^test_block_t)();
+
+int main(int argc, char **argv) {
+    int a;
+
+    void (^test_block_v)();
+    void (^test_block_v2)(int, float);
+
+    void (^test_block_v3)(void (^barg)(int));
+
+    a = 77;
+    test_block_v = ^(){ int local=1; printf("a=%d\n",a+local); };
+    test_block_v();
+    a++;
+    test_block_v();
+
+    __block int b;
+
+    b = 88; 
+    test_block_v2 = ^(int x, float f){ printf("b=%d\n",b); };
+    test_block_v2(1,2.0);
+    b++;
+    test_block_v2(3,4.0);
+    return 7;
+}





More information about the cfe-commits mailing list