[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