[cfe-commits] r126193 - in /cfe/trunk: lib/CodeGen/CGDecl.cpp lib/CodeGen/CGObjC.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenObjC/for-in.m

John McCall rjmccall at apple.com
Mon Feb 21 23:16:58 PST 2011


Author: rjmccall
Date: Tue Feb 22 01:16:58 2011
New Revision: 126193

URL: http://llvm.org/viewvc/llvm-project?rev=126193&view=rev
Log:
Establish the iteration variable of an ObjC for-in loop before
emitting the collection expression.  Fixes some really, really broken
code.


Modified:
    cfe/trunk/lib/CodeGen/CGDecl.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenObjC/for-in.m

Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=126193&r1=126192&r2=126193&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Feb 22 01:16:58 2011
@@ -782,10 +782,12 @@
 }
 
 void CodeGenFunction::EmitAutoVarInit(const AutoVarEmission &emission) {
+  assert(emission.Variable && "emission was not valid!");
+
   // If this was emitted as a global constant, we're done.
   if (emission.wasEmittedAsGlobal()) return;
 
-  const VarDecl &D = emission.Variable;
+  const VarDecl &D = *emission.Variable;
   QualType type = D.getType();
 
   // If this local has an initializer, emit it now.
@@ -940,10 +942,12 @@
 }
 
 void CodeGenFunction::EmitAutoVarCleanups(const AutoVarEmission &emission) {
+  assert(emission.Variable && "emission was not valid!");
+
   // If this was emitted as a global constant, we're done.
   if (emission.wasEmittedAsGlobal()) return;
 
-  const VarDecl &D = emission.Variable;
+  const VarDecl &D = *emission.Variable;
 
   // Handle C++ destruction of variables.
   if (getLangOptions().CPlusPlus) {

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=126193&r1=126192&r2=126193&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Tue Feb 22 01:16:58 2011
@@ -663,6 +663,11 @@
     return;
   }
 
+  // The local variable comes into scope immediately.
+  AutoVarEmission variable = AutoVarEmission::invalid();
+  if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement()))
+    variable = EmitAutoVarAlloca(*cast<VarDecl>(SD->getSingleDecl()));
+
   CGDebugInfo *DI = getDebugInfo();
   if (DI) {
     DI->setLocation(S.getSourceRange().getBegin());
@@ -799,22 +804,23 @@
 
   // Initialize the element variable.
   RunCleanupsScope elementVariableScope(*this);
-  bool elementIsDecl;
+  bool elementIsVariable;
   LValue elementLValue;
   QualType elementType;
   if (const DeclStmt *SD = dyn_cast<DeclStmt>(S.getElement())) {
-    EmitStmt(SD);
-    const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
+    // Initialize the variable, in case it's a __block variable or something.
+    EmitAutoVarInit(variable);
 
+    const VarDecl* D = cast<VarDecl>(SD->getSingleDecl());
     DeclRefExpr tempDRE(const_cast<VarDecl*>(D), D->getType(),
                         VK_LValue, SourceLocation());
     elementLValue = EmitLValue(&tempDRE);
     elementType = D->getType();
-    elementIsDecl = true;
+    elementIsVariable = true;
   } else {
     elementLValue = LValue(); // suppress warning
     elementType = cast<Expr>(S.getElement())->getType();
-    elementIsDecl = false;
+    elementIsVariable = false;
   }
   const llvm::Type *convertedElementType = ConvertType(elementType);
 
@@ -837,11 +843,16 @@
 
   // Make sure we have an l-value.  Yes, this gets evaluated every
   // time through the loop.
-  if (!elementIsDecl)
+  if (!elementIsVariable)
     elementLValue = EmitLValue(cast<Expr>(S.getElement()));
 
   EmitStoreThroughLValue(RValue::get(CurrentItem), elementLValue, elementType);
 
+  // If we do have an element variable, this assignment is the end of
+  // its initialization.
+  if (elementIsVariable)
+    EmitAutoVarCleanups(variable);
+
   // Perform the loop body, setting up break and continue labels.
   BreakContinueStack.push_back(BreakContinue(LoopEnd, AfterBody));
   {
@@ -891,7 +902,7 @@
   // No more elements.
   EmitBlock(EmptyBB);
 
-  if (!elementIsDecl) {
+  if (!elementIsVariable) {
     // If the element was not a declaration, set it to be null.
 
     llvm::Value *null = llvm::Constant::getNullValue(convertedElementType);

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=126193&r1=126192&r2=126193&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Feb 22 01:16:58 2011
@@ -1560,7 +1560,7 @@
   class AutoVarEmission {
     friend class CodeGenFunction;
 
-    const VarDecl &Variable;
+    const VarDecl *Variable;
 
     /// The alignment of the variable.
     CharUnits Alignment;
@@ -1578,13 +1578,18 @@
     /// initializer.
     bool IsConstantAggregate;
 
+    struct Invalid {};
+    AutoVarEmission(Invalid) : Variable(0) {}
+
     AutoVarEmission(const VarDecl &variable)
-      : Variable(variable), Address(0), NRVOFlag(0),
+      : Variable(&variable), Address(0), NRVOFlag(0),
         IsByRef(false), IsConstantAggregate(false) {}
 
     bool wasEmittedAsGlobal() const { return Address == 0; }
 
   public:
+    static AutoVarEmission invalid() { return AutoVarEmission(Invalid()); }
+
     /// Returns the address of the object within this declaration.
     /// Note that this does not chase the forwarding pointer for
     /// __block decls.
@@ -1592,8 +1597,8 @@
       if (!IsByRef) return Address;
 
       return CGF.Builder.CreateStructGEP(Address,
-                                         CGF.getByRefValueLLVMField(&Variable),
-                                         Variable.getNameAsString());
+                                         CGF.getByRefValueLLVMField(Variable),
+                                         Variable->getNameAsString());
     }
   };
   AutoVarEmission EmitAutoVarAlloca(const VarDecl &var);

Modified: cfe/trunk/test/CodeGenObjC/for-in.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/for-in.m?rev=126193&r1=126192&r2=126193&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/for-in.m (original)
+++ cfe/trunk/test/CodeGenObjC/for-in.m Tue Feb 22 01:16:58 2011
@@ -42,3 +42,9 @@
       break;
   }
 }
+
+// rdar://problem/9027663
+void t2(NSArray *array) {
+  for (NSArray *array in array) { // expected-warning {{collection expression type 'NSArray *' may not respond}}
+  }
+}





More information about the cfe-commits mailing list