[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