aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2010-01-14 23:05:52 +0000
committerFariborz Jahanian <fjahanian@apple.com>2010-01-14 23:05:52 +0000
commita73165e47aefbea60312d284343660c9c962c9c3 (patch)
treeb72fbea03a8063cf53264dbc4dc5d3b1a76cd0bd
parentaa97d7051ed3517c7b64787bcb65ae04e1a52594 (diff)
Patch to avoid duplicate declaration of byref structs
for __block variables of same name declared in multiple scopes. Fixes radar 7540194 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93474 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Frontend/RewriteObjC.cpp44
-rw-r--r--test/Rewriter/rewrite-byref-vars.mm35
2 files changed, 70 insertions, 9 deletions
diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp
index 87b1cd40e4..fc9401d290 100644
--- a/lib/Frontend/RewriteObjC.cpp
+++ b/lib/Frontend/RewriteObjC.cpp
@@ -126,6 +126,7 @@ namespace {
// Block related declarations.
llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
+ llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
@@ -252,6 +253,8 @@ namespace {
void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
void RewriteImplementationDecl(Decl *Dcl);
void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr);
+ void RewriteByRefString(std::string &ResultStr, const std::string &Name,
+ ValueDecl *VD);
void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl);
@@ -3760,6 +3763,15 @@ void RewriteObjC::SynthesizeMetaDataIntoBuffer(std::string &Result) {
}
}
+void RewriteObjC::RewriteByRefString(std::string &ResultStr,
+ const std::string &Name,
+ ValueDecl *VD) {
+ assert(BlockByRefDeclNo.count(VD) &&
+ "RewriteByRefString: ByRef decl missing");
+ ResultStr += "struct __Block_byref_" + Name +
+ "_" + utostr(BlockByRefDeclNo[VD]) ;
+}
+
std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
const char *funcName,
std::string Tag) {
@@ -3805,7 +3817,9 @@ std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
E = BlockByRefDecls.end(); I != E; ++I) {
S += " ";
std::string Name = (*I)->getNameAsString();
- std::string TypeString = "struct __Block_byref_" + Name + " *";
+ std::string TypeString;
+ RewriteByRefString(TypeString, Name, (*I));
+ TypeString += " *";
Name = TypeString + Name;
S += Name + " = __cself->" + (*I)->getNameAsString() + "; // bound by ref\n";
}
@@ -3940,7 +3954,8 @@ std::string RewriteObjC::SynthesizeBlockImpl(BlockExpr *CE, std::string Tag,
S += "struct __block_impl *";
Constructor += ", void *" + ArgName;
} else {
- std::string TypeString = "struct __Block_byref_" + FieldName;
+ std::string TypeString;
+ RewriteByRefString(TypeString, FieldName, (*I));
TypeString += " *";
FieldName = TypeString + FieldName;
ArgName = TypeString + ArgName;
@@ -4521,11 +4536,12 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
X = SM->getInstantiationLoc(X);
const char *endBuf = SM->getCharacterData(X);
std::string Name(ND->getNameAsString());
- std::string ByrefType = "struct __Block_byref_";
- ByrefType += Name;
+ std::string ByrefType;
+ RewriteByRefString(ByrefType, Name, ND);
ByrefType += " {\n";
ByrefType += " void *__isa;\n";
- ByrefType += " struct __Block_byref_" + Name + " *__forwarding;\n";
+ RewriteByRefString(ByrefType, Name, ND);
+ ByrefType += " *__forwarding;\n";
ByrefType += " int __flags;\n";
ByrefType += " int __size;\n";
// Add void *__Block_byref_id_object_copy;
@@ -4570,14 +4586,17 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
if (HasCopyAndDispose)
flags |= BLOCK_HAS_COPY_DISPOSE;
Name = ND->getNameAsString();
- ByrefType = "struct __Block_byref_" + Name;
+ ByrefType.clear();
+ RewriteByRefString(ByrefType, Name, ND);
if (!hasInit) {
ByrefType += " " + Name + " = {(void*)";
ByrefType += utostr(isa);
ByrefType += ", &" + Name + ", ";
ByrefType += utostr(flags);
ByrefType += ", ";
- ByrefType += "sizeof(struct __Block_byref_" + Name + ")";
+ ByrefType += "sizeof(";
+ RewriteByRefString(ByrefType, Name, ND);
+ ByrefType += ")";
if (HasCopyAndDispose) {
ByrefType += ", __Block_byref_id_object_copy_";
ByrefType += utostr(flag);
@@ -4599,7 +4618,9 @@ void RewriteObjC::RewriteByRefVar(VarDecl *ND) {
ByrefType += ", &" + Name + ", ";
ByrefType += utostr(flags);
ByrefType += ", ";
- ByrefType += "sizeof(struct __Block_byref_" + Name + "), ";
+ ByrefType += "sizeof(";
+ RewriteByRefString(ByrefType, Name, ND);
+ ByrefType += "), ";
if (HasCopyAndDispose) {
ByrefType += "__Block_byref_id_object_copy_";
ByrefType += utostr(flag);
@@ -4971,8 +4992,13 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
else if (ND->getType()->isFunctionPointerType())
CheckFunctionPointerDecl(ND->getType(), ND);
if (VarDecl *VD = dyn_cast<VarDecl>(SD))
- if (VD->hasAttr<BlocksAttr>())
+ if (VD->hasAttr<BlocksAttr>()) {
+ static unsigned uniqueByrefDeclCount = 0;
+ assert(!BlockByRefDeclNo.count(ND) &&
+ "RewriteFunctionBodyOrGlobalInitializer: Duplicate byref decl");
+ BlockByRefDeclNo[ND] = uniqueByrefDeclCount++;
RewriteByRefVar(VD);
+ }
}
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
diff --git a/test/Rewriter/rewrite-byref-vars.mm b/test/Rewriter/rewrite-byref-vars.mm
new file mode 100644
index 0000000000..581437b5a5
--- /dev/null
+++ b/test/Rewriter/rewrite-byref-vars.mm
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fms-extensions -rewrite-objc -x objective-c++ -fblocks -o - %s
+// radar 7540194
+
+extern "C" __declspec(dllexport) void BreakTheRewriter(int i) {
+ __block int aBlockVariable = 0;
+ void (^aBlock)(void) = ^ {
+ aBlockVariable = 42;
+ };
+ aBlockVariable++;
+ if (i) {
+ __block int bbBlockVariable = 0;
+ void (^aBlock)(void) = ^ {
+ bbBlockVariable = 42;
+ };
+ }
+}
+
+__declspec(dllexport) extern "C" __declspec(dllexport) void XXXXBreakTheRewriter(void) {
+
+ __block int aBlockVariable = 0;
+ void (^aBlock)(void) = ^ {
+ aBlockVariable = 42;
+ };
+ aBlockVariable++;
+ void (^bBlocks)(void) = ^ {
+ aBlockVariable = 43;
+ };
+ void (^c)(void) = ^ {
+ aBlockVariable = 44;
+ };
+
+}
+
+// $CLANG -cc1 -fms-extensions -rewrite-objc -x objective-c++ -fblocks bug.mm
+// g++ -c -D"__declspec(X)=" bug.cpp