[cfe-commits] r98265 - in /cfe/trunk: include/clang/AST/Decl.h lib/Frontend/RewriteObjC.cpp test/Rewriter/rewrite-local-externs-in-block.mm
Fariborz Jahanian
fjahanian at apple.com
Thu Mar 11 10:20:03 PST 2010
Author: fjahanian
Date: Thu Mar 11 12:20:03 2010
New Revision: 98265
URL: http://llvm.org/viewvc/llvm-project?rev=98265&view=rev
Log:
Add tentative support for accessing local variables with
external linkage (static, extern, etc.) in blocks in
rewriter. wip.
Added:
cfe/trunk/test/Rewriter/rewrite-local-externs-in-block.mm
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/Frontend/RewriteObjC.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=98265&r1=98264&r2=98265&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Thu Mar 11 12:20:03 2010
@@ -500,7 +500,8 @@
bool isExternC() const;
/// isBlockVarDecl - Returns true for local variable declarations. Note that
- /// this includes static variables inside of functions.
+ /// this includes static variables inside of functions. It also includes
+ /// variables inside blocks.
///
/// void foo() { int x; static int y; extern int z; }
///
@@ -512,6 +513,17 @@
return false;
}
+ /// isFunctionOrMethodVarDecl - Similar to isBlockVarDecl, but excludes
+ /// variables declared in blocks.
+ bool isFunctionOrMethodVarDecl() const {
+ if (getKind() != Decl::Var)
+ return false;
+ if (const DeclContext *DC = getDeclContext())
+ return DC->getLookupContext()->isFunctionOrMethod() &&
+ DC->getLookupContext()->getDeclKind() != Decl::Block;
+ return false;
+ }
+
/// \brief Determines whether this is a static data member.
///
/// This will only be true in C++, and applies to, e.g., the
Modified: cfe/trunk/lib/Frontend/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/RewriteObjC.cpp?rev=98265&r1=98264&r2=98265&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/RewriteObjC.cpp (original)
+++ cfe/trunk/lib/Frontend/RewriteObjC.cpp Thu Mar 11 12:20:03 2010
@@ -134,7 +134,8 @@
llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDeclsPtrSet;
llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
-
+ llvm::SmallPtrSet<VarDecl *, 8> ImportedLocalExternalDecls;
+
llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
// This maps a property to it's assignment statement.
@@ -372,6 +373,7 @@
void RewriteByRefVar(VarDecl *VD);
std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
Stmt *RewriteBlockDeclRefExpr(Expr *VD);
+ Stmt *RewriteLocalVariableExternalStorage(DeclRefExpr *DRE);
void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
@@ -4025,6 +4027,12 @@
"_" + utostr(BlockByRefDeclNo[VD]) ;
}
+static bool HasLocalVariableExternalStorage(ValueDecl *VD) {
+ if (VarDecl *Var = dyn_cast<VarDecl>(VD))
+ return (Var->isFunctionOrMethodVarDecl() && !Var->hasLocalStorage());
+ return false;
+}
+
std::string RewriteObjC::SynthesizeBlockFunc(BlockExpr *CE, int i,
const char *funcName,
std::string Tag) {
@@ -4099,7 +4107,10 @@
}
else {
std::string Name = (*I)->getNameAsString();
- (*I)->getType().getAsStringInternal(Name, Context->PrintingPolicy);
+ QualType QT = (*I)->getType();
+ if (HasLocalVariableExternalStorage(*I))
+ QT = Context->getPointerType(QT);
+ QT.getAsStringInternal(Name, Context->PrintingPolicy);
S += Name + " = __cself->" +
(*I)->getNameAsString() + "; // bound by copy\n";
}
@@ -4188,8 +4199,11 @@
S += "struct __block_impl *";
Constructor += ", void *" + ArgName;
} else {
- (*I)->getType().getAsStringInternal(FieldName, Context->PrintingPolicy);
- (*I)->getType().getAsStringInternal(ArgName, Context->PrintingPolicy);
+ QualType QT = (*I)->getType();
+ if (HasLocalVariableExternalStorage(*I))
+ QT = Context->getPointerType(QT);
+ QT.getAsStringInternal(FieldName, Context->PrintingPolicy);
+ QT.getAsStringInternal(ArgName, Context->PrintingPolicy);
Constructor += ", " + ArgName;
}
S += FieldName + ";\n";
@@ -4419,10 +4433,19 @@
GetBlockDeclRefExprs(*CI);
}
// Handle specific things.
- if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
+ if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
// FIXME: Handle enums.
if (!isa<FunctionDecl>(CDRE->getDecl()))
BlockDeclRefs.push_back(CDRE);
+ }
+ else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S))
+ if (HasLocalVariableExternalStorage(DRE->getDecl())) {
+ BlockDeclRefExpr *BDRE =
+ new (Context)BlockDeclRefExpr(DRE->getDecl(), DRE->getType(),
+ DRE->getLocation(), false);
+ BlockDeclRefs.push_back(BDRE);
+ }
+
return;
}
@@ -4445,10 +4468,16 @@
}
// Handle specific things.
- if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S))
+ if (BlockDeclRefExpr *CDRE = dyn_cast<BlockDeclRefExpr>(S)) {
if (!isa<FunctionDecl>(CDRE->getDecl()) &&
!InnerContexts.count(CDRE->getDecl()->getDeclContext()))
InnerBlockDeclRefs.push_back(CDRE);
+ }
+ else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(S)) {
+ if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl()))
+ if (Var->isFunctionOrMethodVarDecl())
+ ImportedLocalExternalDecls.insert(Var);
+ }
return;
}
@@ -4611,6 +4640,23 @@
return PE;
}
+// Rewrites the imported local variable V with external storage
+// (static, extern, etc.) as *V
+//
+Stmt *RewriteObjC::RewriteLocalVariableExternalStorage(DeclRefExpr *DRE) {
+ ValueDecl *VD = DRE->getDecl();
+ if (VarDecl *Var = dyn_cast<VarDecl>(VD))
+ if (!ImportedLocalExternalDecls.count(Var))
+ return DRE;
+ Expr *Exp = new (Context) UnaryOperator(DRE, UnaryOperator::Deref,
+ DRE->getType(), DRE->getLocation());
+ // Need parens to enforce precedence.
+ ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(),
+ Exp);
+ ReplaceStmt(DRE, PE);
+ return PE;
+}
+
void RewriteObjC::RewriteCastExpr(CStyleCastExpr *CE) {
SourceLocation LocStart = CE->getLParenLoc();
SourceLocation LocEnd = CE->getRParenLoc();
@@ -5130,6 +5176,13 @@
} else {
FD = SynthBlockInitFunctionDecl((*I)->getNameAsCString());
Exp = new (Context) DeclRefExpr(FD, FD->getType(), SourceLocation());
+ if (HasLocalVariableExternalStorage(*I)) {
+ QualType QT = (*I)->getType();
+ QT = Context->getPointerType(QT);
+ Exp = new (Context) UnaryOperator(Exp, UnaryOperator::AddrOf, QT,
+ SourceLocation());
+ }
+
}
InitExprs.push_back(Exp);
}
@@ -5244,11 +5297,12 @@
llvm::SmallVector<BlockDeclRefExpr *, 8> InnerBlockDeclRefs;
llvm::SmallPtrSet<const DeclContext *, 8> InnerContexts;
InnerContexts.insert(BE->getBlockDecl());
+ ImportedLocalExternalDecls.clear();
GetInnerBlockDeclRefExprs(BE->getBody(),
InnerBlockDeclRefs, InnerContexts);
// Rewrite the block body in place.
RewriteFunctionBodyOrGlobalInitializer(BE->getBody());
-
+ ImportedLocalExternalDecls.clear();
// Now we snarf the rewritten text and stash it away for later use.
std::string Str = Rewrite.getRewrittenText(BE->getSourceRange());
RewrittenBlockExprs[BE] = Str;
@@ -5431,6 +5485,8 @@
ValueDecl *VD = DRE->getDecl();
if (VD->hasAttr<BlocksAttr>())
return RewriteBlockDeclRefExpr(DRE);
+ if (HasLocalVariableExternalStorage(VD))
+ return RewriteLocalVariableExternalStorage(DRE);
}
if (CallExpr *CE = dyn_cast<CallExpr>(S)) {
Added: cfe/trunk/test/Rewriter/rewrite-local-externs-in-block.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Rewriter/rewrite-local-externs-in-block.mm?rev=98265&view=auto
==============================================================================
--- cfe/trunk/test/Rewriter/rewrite-local-externs-in-block.mm (added)
+++ cfe/trunk/test/Rewriter/rewrite-local-externs-in-block.mm Thu Mar 11 12:20:03 2010
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -x objective-c++ -Wno-return-type -fblocks -fms-extensions -rewrite-objc %s -o %t-rw.cpp
+// RUN: %clang_cc1 -fsyntax-only -Wno-address-of-temporary -D"SEL=void*" -D"__declspec(X)=" %t-rw.cpp
+// radar 7735987
+
+extern "C" int printf(const char*, ...);
+
+void bar(void (^block)()) {
+ block();
+}
+
+int main() {
+ static int myArr[3] = {1, 2, 3};
+ printf ("%d %d %d\n", myArr[0], myArr[1], myArr[2]);
+
+ bar(^{
+ printf ("%d %d %d\n", myArr[0], myArr[1], myArr[2]);
+ myArr[0] = 42;
+ myArr[2] = 100;
+ printf ("%d %d %d\n", myArr[0], myArr[1], myArr[2]);
+ });
+
+ printf ("%d %d %d\n", myArr[0], myArr[1], myArr[2]);
+}
More information about the cfe-commits
mailing list