[cfe-commits] r150132 - /cfe/trunk/lib/Sema/SemaExpr.cpp
Douglas Gregor
dgregor at apple.com
Wed Feb 8 17:56:40 PST 2012
Author: dgregor
Date: Wed Feb 8 19:56:40 2012
New Revision: 150132
URL: http://llvm.org/viewvc/llvm-project?rev=150132&view=rev
Log:
Factor the logic for capturing variables in a lambda into its own
function; it's going to get longer soon. No functionality change.
Modified:
cfe/trunk/lib/Sema/SemaExpr.cpp
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=150132&r1=150131&r2=150132&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Feb 8 19:56:40 2012
@@ -9534,6 +9534,90 @@
return false;
}
+/// \brief Capture the given variable in the given lambda expression.
+static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI,
+ VarDecl *Var, QualType Type,
+ SourceLocation Loc, bool ByRef) {
+ CXXRecordDecl *Lambda = LSI->Lambda;
+ QualType FieldType;
+ if (ByRef) {
+ // C++11 [expr.prim.lambda]p15:
+ // An entity is captured by reference if it is implicitly or
+ // explicitly captured but not captured by copy. It is
+ // unspecified whether additional unnamed non-static data
+ // members are declared in the closure type for entities
+ // captured by reference.
+ FieldType = S.Context.getLValueReferenceType(Type.getNonReferenceType());
+ } else {
+ // C++11 [expr.prim.lambda]p14:
+ // For each entity captured by copy, an unnamed non-static
+ // data member is declared in the closure type. The
+ // declaration order of these members is unspecified. The type
+ // of such a data member is the type of the corresponding
+ // captured entity if the entity is not a reference to an
+ // object, or the referenced type otherwise. [Note: If the
+ // captured entity is a reference to a function, the
+ // corresponding data member is also a reference to a
+ // function. - end note ]
+ if (const ReferenceType *RefType = Type->getAs<ReferenceType>()) {
+ if (!RefType->getPointeeType()->isFunctionType())
+ FieldType = RefType->getPointeeType();
+ else
+ FieldType = Type;
+ } else {
+ FieldType = Type;
+ }
+ }
+
+ // Build the non-static data member.
+ FieldDecl *Field
+ = FieldDecl::Create(S.Context, Lambda, Loc, Loc, 0, FieldType,
+ S.Context.getTrivialTypeSourceInfo(FieldType, Loc),
+ 0, false, false);
+ Field->setImplicit(true);
+ Field->setAccess(AS_private);
+
+ // C++11 [expr.prim.lambda]p21:
+ // When the lambda-expression is evaluated, the entities that
+ // are captured by copy are used to direct-initialize each
+ // corresponding non-static data member of the resulting closure
+ // object. (For array members, the array elements are
+ // direct-initialized in increasing subscript order.) These
+ // initializations are performed in the (unspecified) order in
+ // 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
+ S.PushExpressionEvaluationContext(Sema::PotentiallyEvaluated);
+
+ Expr *Ref = new (S.Context) DeclRefExpr(Var, Type.getNonReferenceType(),
+ VK_LValue, Loc);
+ InitializedEntity InitEntity
+ = InitializedEntity::InitializeMember(Field, /*Parent=*/0);
+ InitializationKind InitKind
+ = InitializationKind::CreateDirect(Loc, Loc, Loc);
+ InitializationSequence Init(S, InitEntity, InitKind, &Ref, 1);
+ ExprResult Result(true);
+ if (!Init.Diagnose(S, InitEntity, InitKind, &Ref, 1))
+ Result = Init.Perform(S, InitEntity, InitKind,
+ MultiExprArg(S, &Ref, 1));
+
+ // If this initialization requires any cleanups (e.g., due to a
+ // default argument to a copy constructor), note that for the
+ // lambda.
+ if (S.ExprNeedsCleanups)
+ LSI->ExprNeedsCleanups = true;
+
+ // Exit the expression evaluation context used for the capture.
+ S.CleanupVarDeclMarking();
+ S.DiscardCleanupsInEvaluationContext();
+ S.PopExpressionEvaluationContext();
+ return Result;
+}
+
// Check if the variable needs to be captured; if so, try to perform
// the capture.
// FIXME: Add support for explicit captures.
@@ -9652,88 +9736,10 @@
Expr *copyExpr = 0;
const RecordType *rtype;
if (isLambda) {
- LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);
- CXXRecordDecl *Lambda = LSI->Lambda;
- QualType FieldType;
- if (byRef) {
- // C++11 [expr.prim.lambda]p15:
- // An entity is captured by reference if it is implicitly or
- // explicitly captured but not captured by copy. It is
- // unspecified whether additional unnamed non-static data
- // members are declared in the closure type for entities
- // captured by reference.
- FieldType = Context.getLValueReferenceType(type.getNonReferenceType());
- } else {
- // C++11 [expr.prim.lambda]p14:
- //
- // For each entity captured by copy, an unnamed non-static
- // data member is declared in the closure type. The
- // declaration order of these members is unspecified. The type
- // of such a data member is the type of the corresponding
- // captured entity if the entity is not a reference to an
- // object, or the referenced type otherwise. [Note: If the
- // captured entity is a reference to a function, the
- // corresponding data member is also a reference to a
- // function. - end note ]
- if (const ReferenceType *RefType
- = type->getAs<ReferenceType>()) {
- if (!RefType->getPointeeType()->isFunctionType())
- FieldType = RefType->getPointeeType();
- else
- FieldType = type;
- } else {
- FieldType = type;
- }
- }
-
- // Build the non-static data member.
- FieldDecl *Field
- = FieldDecl::Create(Context, Lambda, loc, loc, 0, FieldType,
- Context.getTrivialTypeSourceInfo(FieldType, loc),
- 0, false, false);
- Field->setImplicit(true);
- Field->setAccess(AS_private);
-
- // C++11 [expr.prim.lambda]p21:
- // When the lambda-expression is evaluated, the entities that
- // are captured by copy are used to direct-initialize each
- // corresponding non-static data member of the resulting closure
- // object. (For array members, the array elements are
- // direct-initialized in increasing subscript order.) These
- // initializations are performed in the (unspecified) order in
- // 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
- PushExpressionEvaluationContext(PotentiallyEvaluated);
-
- Expr *Ref = new (Context) DeclRefExpr(var, type.getNonReferenceType(),
- VK_LValue, loc);
- InitializedEntity InitEntity
- = InitializedEntity::InitializeMember(Field, /*Parent=*/0);
- InitializationKind InitKind
- = InitializationKind::CreateDirect(loc, loc, loc);
- InitializationSequence Init(*this, InitEntity, InitKind, &Ref, 1);
- if (!Init.Diagnose(*this, InitEntity, InitKind, &Ref, 1)) {
- ExprResult Result = Init.Perform(*this, InitEntity, InitKind,
- MultiExprArg(*this, &Ref, 1));
- if (!Result.isInvalid())
- copyExpr = Result.take();
- }
-
- // If this initialization requires any cleanups (e.g., due to a
- // default argument to a copy constructor), note that for the
- // lambda.
- if (ExprNeedsCleanups)
- LSI->ExprNeedsCleanups = true;
-
- // Exit the expression evaluation context used for the capture.
- CleanupVarDeclMarking();
- DiscardCleanupsInEvaluationContext();
- PopExpressionEvaluationContext();
+ ExprResult Result = captureInLambda(*this, cast<LambdaScopeInfo>(CSI),
+ var, type, loc, byRef);
+ if (!Result.isInvalid())
+ copyExpr = Result.take();
} else if (!byRef && getLangOptions().CPlusPlus &&
(rtype = type.getNonReferenceType()->getAs<RecordType>())) {
// The capture logic needs the destructor, so make sure we mark it.
More information about the cfe-commits
mailing list