[cfe-commits] r150138 - in /cfe/trunk: lib/Sema/SemaExpr.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp

Douglas Gregor dgregor at apple.com
Wed Feb 8 18:45:48 PST 2012


Author: dgregor
Date: Wed Feb  8 20:45:47 2012
New Revision: 150138

URL: http://llvm.org/viewvc/llvm-project?rev=150138&view=rev
Log:
Implement capture-by-copy for arrays in lambdas.

Modified:
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=150138&r1=150137&r2=150138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb  8 20:45:47 2012
@@ -9588,7 +9588,6 @@
   //   which the non-static data members are declared.
   //
   // FIXME: Introduce an initialization entity for lambda captures.
-  // FIXME: Totally broken for arrays.
       
   // Introduce a new evaluation context for the initialization, so that
   // temporaries introduced as part of the capture
@@ -9596,14 +9595,74 @@
 
   Expr *Ref = new (S.Context) DeclRefExpr(Var, Type.getNonReferenceType(),
                                           VK_LValue, Loc);
-  InitializedEntity InitEntity
-    = InitializedEntity::InitializeMember(Field, /*Parent=*/0);
+
+  // When the field has array type, create index variables for each
+  // dimension of the array. We use these index variables to subscript
+  // the source array, and other clients (e.g., CodeGen) will perform
+  // the necessary iteration with these index variables.
+  SmallVector<VarDecl *, 4> IndexVariables;
+  bool InitializingArray = false;
+  QualType BaseType = FieldType;
+  QualType SizeType = S.Context.getSizeType();
+  while (const ConstantArrayType *Array
+                        = S.Context.getAsConstantArrayType(BaseType)) {
+    InitializingArray = true;
+    
+    // Create the iteration variable for this array index.
+    IdentifierInfo *IterationVarName = 0;
+    {
+      SmallString<8> Str;
+      llvm::raw_svector_ostream OS(Str);
+      OS << "__i" << IndexVariables.size();
+      IterationVarName = &S.Context.Idents.get(OS.str());
+    }
+    VarDecl *IterationVar
+      = VarDecl::Create(S.Context, S.CurContext, Loc, Loc,
+                        IterationVarName, SizeType,
+                        S.Context.getTrivialTypeSourceInfo(SizeType, Loc),
+                        SC_None, SC_None);
+    IndexVariables.push_back(IterationVar);
+
+    // Create a reference to the iteration variable.
+    ExprResult IterationVarRef
+      = S.BuildDeclRefExpr(IterationVar, SizeType, VK_LValue, Loc);
+    assert(!IterationVarRef.isInvalid() &&
+           "Reference to invented variable cannot fail!");
+    IterationVarRef = S.DefaultLvalueConversion(IterationVarRef.take());
+    assert(!IterationVarRef.isInvalid() &&
+           "Conversion of invented variable cannot fail!");
+    
+    // Subscript the array with this iteration variable.
+    ExprResult Subscript = S.CreateBuiltinArraySubscriptExpr(
+                             Ref, Loc, IterationVarRef.take(), Loc);
+    if (Subscript.isInvalid()) {
+      S.CleanupVarDeclMarking();
+      S.DiscardCleanupsInEvaluationContext();
+      S.PopExpressionEvaluationContext();
+      return ExprError();
+    }
+
+    Ref = Subscript.take();
+    BaseType = Array->getElementType();
+  }
+
+  // Construct the entity that we will be initializing. For an array, this
+  // will be first element in the array, which may require several levels
+  // of array-subscript entities. 
+  SmallVector<InitializedEntity, 4> Entities;
+  Entities.reserve(1 + IndexVariables.size());
+  Entities.push_back(InitializedEntity::InitializeMember(Field));
+  for (unsigned I = 0, N = IndexVariables.size(); I != N; ++I)
+    Entities.push_back(InitializedEntity::InitializeElement(S.Context,
+                                                            0,
+                                                            Entities.back()));
+
   InitializationKind InitKind
     = InitializationKind::CreateDirect(Loc, Loc, Loc);
-  InitializationSequence Init(S, InitEntity, InitKind, &Ref, 1);
+  InitializationSequence Init(S, Entities.back(), InitKind, &Ref, 1);
   ExprResult Result(true);
-  if (!Init.Diagnose(S, InitEntity, InitKind, &Ref, 1))
-    Result = Init.Perform(S, InitEntity, InitKind, 
+  if (!Init.Diagnose(S, Entities.back(), InitKind, &Ref, 1))
+    Result = Init.Perform(S, Entities.back(), InitKind, 
                           MultiExprArg(S, &Ref, 1));
 
   // If this initialization requires any cleanups (e.g., due to a
@@ -9617,7 +9676,7 @@
   S.DiscardCleanupsInEvaluationContext();
   S.PopExpressionEvaluationContext();
   return Result;
-}                           
+}
 
 // Check if the variable needs to be captured; if so, try to perform
 // the capture.

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp?rev=150138&r1=150137&r2=150138&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p14.cpp Wed Feb  8 20:45:47 2012
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
 
+template<typename T> void capture(const T&);
+
 class NonCopyable {
   NonCopyable(const NonCopyable&); // expected-note 2 {{implicitly declared private here}}
 };
@@ -19,6 +21,7 @@
 };
 
 struct CopyCtorDefault {
+  CopyCtorDefault();
   CopyCtorDefault(const CopyCtorDefault&, NonTrivial nt = NonTrivial());
 
   void foo() const;
@@ -28,7 +31,17 @@
   (void)[=] () -> void { cct.foo(); }; // expected-error{{lambda expressions are not supported yet}}
 }
 
-// FIXME: arrays!
+struct ExpectedArrayLayout {
+  CopyCtorDefault array[3];
+};
+
+void capture_array() {
+  CopyCtorDefault array[3];
+  auto x = [=]() -> void { // expected-error{{lambda expressions are not supported yet}}
+    capture(array[0]);
+  };
+  static_assert(sizeof(x) == sizeof(ExpectedArrayLayout), "layout mismatch");
+}
 
 // Check for the expected non-static data members.
 
@@ -37,8 +50,6 @@
   short b;
 };
 
-template<typename T> void capture(const T&);
-
 void test_layout(char a, short b) {
   auto x = [=] () -> void { // expected-error{{lambda expressions are not supported yet}}
     capture(a);

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp?rev=150138&r1=150137&r2=150138&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p15.cpp Wed Feb  8 20:45:47 2012
@@ -5,6 +5,8 @@
 };
 
 void capture_by_ref(NonCopyable nc, NonCopyable &ncr) {
+  int array[3];
   (void)[&nc] () -> void {}; // expected-error{{lambda expressions are not supported yet}}
   (void)[&ncr] () -> void {}; // expected-error{{lambda expressions are not supported yet}}
+  (void)[&array] () -> void {}; // expected-error{{lambda expressions are not supported yet}}
 }





More information about the cfe-commits mailing list