[cfe-commits] r102138 - in /cfe/trunk: lib/Sema/SemaStmt.cpp lib/Sema/TreeTransform.h test/SemaObjCXX/instantiate-stmt.mm

Douglas Gregor dgregor at apple.com
Thu Apr 22 16:10:45 PDT 2010


Author: dgregor
Date: Thu Apr 22 18:10:45 2010
New Revision: 102138

URL: http://llvm.org/viewvc/llvm-project?rev=102138&view=rev
Log:
Template instantiation for the Objective-C "fast enumeration"
statement, i.e., 

  for (element in collection) {
    // do something
  }


Modified:
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/test/SemaObjCXX/instantiate-stmt.mm

Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=102138&r1=102137&r2=102138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Thu Apr 22 18:10:45 2010
@@ -988,19 +988,22 @@
         return StmtError(Diag(VD->getLocation(),
                               diag::err_non_variable_decl_in_for));
     } else {
-      if (cast<Expr>(First)->isLvalue(Context) != Expr::LV_Valid)
+      Expr *FirstE = cast<Expr>(First);
+      if (!FirstE->isTypeDependent() &&
+          FirstE->isLvalue(Context) != Expr::LV_Valid)
         return StmtError(Diag(First->getLocStart(),
                    diag::err_selector_element_not_lvalue)
           << First->getSourceRange());
 
       FirstType = static_cast<Expr*>(First)->getType();
     }
-    if (!FirstType->isObjCObjectPointerType() &&
+    if (!FirstType->isDependentType() &&
+        !FirstType->isObjCObjectPointerType() &&
         !FirstType->isBlockPointerType())
         Diag(ForLoc, diag::err_selector_element_type)
           << FirstType << First->getSourceRange();
   }
-  if (Second) {
+  if (Second && !Second->isTypeDependent()) {
     DefaultFunctionArrayLvalueConversion(Second);
     QualType SecondType = Second->getType();
     if (!SecondType->isObjCObjectPointerType())

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=102138&r1=102137&r2=102138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Apr 22 18:10:45 2010
@@ -901,7 +901,6 @@
   
   /// \brief Build a new Objective-C @synchronized statement.
   ///
-  ///
   /// By default, performs semantic analysis to build the new statement.
   /// Subclasses may override this routine to provide different behavior.
   OwningStmtResult RebuildObjCAtSynchronizedStmt(SourceLocation AtLoc,
@@ -910,6 +909,23 @@
     return getSema().ActOnObjCAtSynchronizedStmt(AtLoc, move(Object),
                                                  move(Body));
   }
+
+  /// \brief Build a new Objective-C fast enumeration statement.
+  ///
+  /// By default, performs semantic analysis to build the new statement.
+  /// Subclasses may override this routine to provide different behavior.
+  OwningStmtResult RebuildObjCForCollectionStmt(SourceLocation ForLoc,
+                                                SourceLocation LParenLoc,
+                                                StmtArg Element,
+                                                ExprArg Collection,
+                                                SourceLocation RParenLoc,
+                                                StmtArg Body) {
+    return getSema().ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
+                                                move(Element), 
+                                                move(Collection),
+                                                RParenLoc,
+                                                move(Body));
+  }
   
   /// \brief Build a new C++ exception declaration.
   ///
@@ -3713,9 +3729,35 @@
 Sema::OwningStmtResult
 TreeTransform<Derived>::TransformObjCForCollectionStmt(
                                                   ObjCForCollectionStmt *S) {
-  // FIXME: Implement this
-  assert(false && "Cannot transform an Objective-C for-each statement");
-  return SemaRef.Owned(S->Retain());
+  // Transform the element statement.
+  OwningStmtResult Element = getDerived().TransformStmt(S->getElement());
+  if (Element.isInvalid())
+    return SemaRef.StmtError();
+  
+  // Transform the collection expression.
+  OwningExprResult Collection = getDerived().TransformExpr(S->getCollection());
+  if (Collection.isInvalid())
+    return SemaRef.StmtError();
+  
+  // Transform the body.
+  OwningStmtResult Body = getDerived().TransformStmt(S->getBody());
+  if (Body.isInvalid())
+    return SemaRef.StmtError();
+  
+  // If nothing changed, just retain this statement.
+  if (!getDerived().AlwaysRebuild() &&
+      Element.get() == S->getElement() &&
+      Collection.get() == S->getCollection() &&
+      Body.get() == S->getBody())
+    return SemaRef.Owned(S->Retain());
+  
+  // Build a new statement.
+  return getDerived().RebuildObjCForCollectionStmt(S->getForLoc(),
+                                                   /*FIXME:*/S->getForLoc(),
+                                                   move(Element),
+                                                   move(Collection),
+                                                   S->getRParenLoc(),
+                                                   move(Body));
 }
 
 

Modified: cfe/trunk/test/SemaObjCXX/instantiate-stmt.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjCXX/instantiate-stmt.mm?rev=102138&r1=102137&r2=102138&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjCXX/instantiate-stmt.mm (original)
+++ cfe/trunk/test/SemaObjCXX/instantiate-stmt.mm Thu Apr 22 18:10:45 2010
@@ -22,3 +22,38 @@
 
 template void synchronized_test(NSException *);
 template void synchronized_test(int); // expected-note{{in instantiation of}}
+
+// fast enumeration
+ at interface NSArray
+ at end
+
+ at interface NSString
+ at end
+
+struct vector {};
+
+template<typename T> void eat(T);
+
+template<typename E, typename T>
+void fast_enumeration_test(T collection) {
+  for (E element in collection) { // expected-error{{selector element type 'int' is not a valid object}} \
+    // expected-error{{collection expression type 'vector' is not a valid object}}
+    eat(element);
+  }
+
+  E element;
+  for (element in collection) // expected-error{{selector element type 'int' is not a valid object}} \
+    // expected-error{{collection expression type 'vector' is not a valid object}}
+    eat(element);
+
+  for (NSString *str in collection) // expected-error{{collection expression type 'vector' is not a valid object}}
+    eat(str);
+
+  NSString *str;
+  for (str in collection) // expected-error{{collection expression type 'vector' is not a valid object}}
+    eat(str);
+}
+
+template void fast_enumeration_test<NSString *>(NSArray*);
+template void fast_enumeration_test<int>(NSArray*); // expected-note{{in instantiation of}}
+template void fast_enumeration_test<NSString *>(vector); // expected-note{{in instantiation of}}





More information about the cfe-commits mailing list