[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