[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