[cfe-commits] r150089 - in /cfe/trunk/lib/Sema: CMakeLists.txt SemaExprCXX.cpp SemaLambda.cpp

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


Author: dgregor
Date: Wed Feb  8 15:18:48 2012
New Revision: 150089

URL: http://llvm.org/viewvc/llvm-project?rev=150089&view=rev
Log:
Factor C++11 lambda expressions implementation into a separate
file. No functionality change.

Added:
    cfe/trunk/lib/Sema/SemaLambda.cpp   (with props)
Modified:
    cfe/trunk/lib/Sema/CMakeLists.txt
    cfe/trunk/lib/Sema/SemaExprCXX.cpp

Modified: cfe/trunk/lib/Sema/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=150089&r1=150088&r2=150089&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/CMakeLists.txt (original)
+++ cfe/trunk/lib/Sema/CMakeLists.txt Wed Feb  8 15:18:48 2012
@@ -29,6 +29,7 @@
   SemaExprObjC.cpp
   SemaFixItUtils.cpp
   SemaInit.cpp
+  SemaLambda.cpp
   SemaLookup.cpp
   SemaObjCProperty.cpp
   SemaOverload.cpp

Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=150089&r1=150088&r2=150089&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Feb  8 15:18:48 2012
@@ -4870,333 +4870,3 @@
   
   return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo);
 }
-
-//===----------------------------------------------------------------------===//
-// Lambdas.
-//===----------------------------------------------------------------------===//
-
-void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
-                                        Declarator &ParamInfo,
-                                        Scope *CurScope) {
-  DeclContext *DC = CurContext;
-  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
-    DC = DC->getParent();
-
-  // Start constructing the lambda class.
-  CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC,
-                                               Intro.Range.getBegin(),
-                                               /*IdLoc=*/SourceLocation(),
-                                               /*Id=*/0);
-  Class->startDefinition();
-  Class->setLambda(true);
-  CurContext->addDecl(Class);
-
-  // Build the call operator; we don't really have all the relevant information
-  // at this point, but we need something to attach child declarations to.
-  QualType MethodTy;
-  TypeSourceInfo *MethodTyInfo;
-  bool ExplicitParams = true;
-  SourceLocation EndLoc;
-  if (ParamInfo.getNumTypeObjects() == 0) {
-    // C++11 [expr.prim.lambda]p4:
-    //   If a lambda-expression does not include a lambda-declarator, it is as 
-    //   if the lambda-declarator were ().
-    FunctionProtoType::ExtProtoInfo EPI;
-    EPI.TypeQuals |= DeclSpec::TQ_const;
-    MethodTy = Context.getFunctionType(Context.DependentTy,
-                                       /*Args=*/0, /*NumArgs=*/0, EPI);
-    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
-    ExplicitParams = false;
-    EndLoc = Intro.Range.getEnd();
-  } else {
-    assert(ParamInfo.isFunctionDeclarator() &&
-           "lambda-declarator is a function");
-    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
-    
-    // C++11 [expr.prim.lambda]p5:
-    //   This function call operator is declared const (9.3.1) if and only if 
-    //   the lambda-expression’s parameter-declaration-clause is not followed 
-    //   by mutable. It is neither virtual nor declared volatile. [...]
-    if (!FTI.hasMutableQualifier())
-      FTI.TypeQuals |= DeclSpec::TQ_const;
-    
-    // C++11 [expr.prim.lambda]p5:
-    //   [...] Default arguments (8.3.6) shall not be specified in the 
-    //   parameter-declaration-clause of a lambda-declarator.
-    CheckExtraCXXDefaultArguments(ParamInfo);
-    
-    MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
-    // FIXME: Can these asserts actually fail?
-    assert(MethodTyInfo && "no type from lambda-declarator");
-    MethodTy = MethodTyInfo->getType();
-    assert(!MethodTy.isNull() && "no type from lambda declarator");
-    EndLoc = ParamInfo.getSourceRange().getEnd();
-  }
-  
-  // C++11 [expr.prim.lambda]p5:
-  //   The closure type for a lambda-expression has a public inline function 
-  //   call operator (13.5.4) whose parameters and return type are described by
-  //   the lambda-expression’s parameter-declaration-clause and 
-  //   trailing-return-type respectively.
-  DeclarationName MethodName
-    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
-  DeclarationNameLoc MethodNameLoc;
-  MethodNameLoc.CXXOperatorName.BeginOpNameLoc
-    = Intro.Range.getBegin().getRawEncoding();
-  MethodNameLoc.CXXOperatorName.EndOpNameLoc
-    = Intro.Range.getEnd().getRawEncoding();
-  CXXMethodDecl *Method
-    = CXXMethodDecl::Create(Context, Class, EndLoc,
-                            DeclarationNameInfo(MethodName, 
-                                                Intro.Range.getBegin(),
-                                                MethodNameLoc),
-                            MethodTy, MethodTyInfo,
-                            /*isStatic=*/false,
-                            SC_None,
-                            /*isInline=*/true,
-                            /*isConstExpr=*/false,
-                            EndLoc);
-  Method->setAccess(AS_public);
-  Class->addDecl(Method);
-  Method->setLexicalDeclContext(DC); // FIXME: Minor hack.
-  
-  ProcessDeclAttributes(CurScope, Method, ParamInfo);
-  
-  // Enter a new evaluation context to insulate the block from any
-  // cleanups from the enclosing full-expression.
-  PushExpressionEvaluationContext(PotentiallyEvaluated);
-  
-  PushDeclContext(CurScope, Method);
-    
-  // Introduce the lambda scope.
-  PushLambdaScope(Class, Method);
-  LambdaScopeInfo *LSI = getCurLambda();
-  if (Intro.Default == LCD_ByCopy)
-    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
-  else if (Intro.Default == LCD_ByRef)
-    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
-  LSI->IntroducerRange = Intro.Range;
-  LSI->ExplicitParams = ExplicitParams;
-  LSI->Mutable = (Method->getTypeQualifiers() & Qualifiers::Const) == 0;
- 
-  // Handle explicit captures.
-  for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
-         C = Intro.Captures.begin(), 
-         E = Intro.Captures.end(); 
-       C != E; ++C) {
-    if (C->Kind == LCK_This) {
-      // C++11 [expr.prim.lambda]p8:
-      //   An identifier or this shall not appear more than once in a 
-      //   lambda-capture.
-      if (LSI->isCXXThisCaptured()) {
-        Diag(C->Loc, diag::err_capture_more_than_once) 
-          << "'this'"
-          << SourceRange(LSI->getCXXThisCapture().getLocation());
-        continue;
-      }
-
-      // C++11 [expr.prim.lambda]p8:
-      //   If a lambda-capture includes a capture-default that is =, the 
-      //   lambda-capture shall not contain this [...].
-      if (Intro.Default == LCD_ByCopy) {
-        Diag(C->Loc, diag::err_this_capture_with_copy_default);
-        continue;
-      }
-
-      // C++11 [expr.prim.lambda]p12:
-      //   If this is captured by a local lambda expression, its nearest
-      //   enclosing function shall be a non-static member function.
-      QualType ThisCaptureType = getCurrentThisType();
-      if (ThisCaptureType.isNull()) {
-        Diag(C->Loc, diag::err_this_capture) << true;
-        continue;
-      }
-      
-      CheckCXXThisCapture(C->Loc, /*Explicit=*/true);
-      continue;
-    }
-
-    assert(C->Id && "missing identifier for capture");
-
-    // C++11 [expr.prim.lambda]p8:
-    //   If a lambda-capture includes a capture-default that is &, the 
-    //   identifiers in the lambda-capture shall not be preceded by &.
-    //   If a lambda-capture includes a capture-default that is =, [...]
-    //   each identifier it contains shall be preceded by &.
-    if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
-      Diag(C->Loc, diag::err_reference_capture_with_reference_default);
-      continue;
-    } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
-      Diag(C->Loc, diag::err_copy_capture_with_copy_default);
-      continue;
-    }
-
-    DeclarationNameInfo Name(C->Id, C->Loc);
-    LookupResult R(*this, Name, LookupOrdinaryName);
-    LookupName(R, CurScope);
-    if (R.isAmbiguous())
-      continue;
-    if (R.empty()) {
-      // FIXME: Disable corrections that would add qualification?
-      CXXScopeSpec ScopeSpec;
-      DeclFilterCCC<VarDecl> Validator;
-      if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
-        continue;
-    }
-
-    // C++11 [expr.prim.lambda]p10:
-    //   The identifiers in a capture-list are looked up using the usual rules
-    //   for unqualified name lookup (3.4.1); each such lookup shall find a 
-    //   variable with automatic storage duration declared in the reaching 
-    //   scope of the local lambda expression.
-    // FIXME: Check reaching scope. 
-    VarDecl *Var = R.getAsSingle<VarDecl>();
-    if (!Var) {
-      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
-      continue;
-    }
-
-    if (!Var->hasLocalStorage()) {
-      Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
-      Diag(Var->getLocation(), diag::note_previous_decl) << C->Id;
-      continue;
-    }
-
-    // C++11 [expr.prim.lambda]p8:
-    //   An identifier or this shall not appear more than once in a 
-    //   lambda-capture.
-    if (LSI->isCaptured(Var)) {
-      Diag(C->Loc, diag::err_capture_more_than_once) 
-        << C->Id
-        << SourceRange(LSI->getCapture(Var).getLocation());
-      continue;
-    }
-
-    TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
-                                                 TryCapture_ExplicitByVal;
-    TryCaptureVar(Var, C->Loc, Kind);
-  }
-  LSI->finishedExplicitCaptures();
-
-  // Set the parameters on the decl, if specified.
-  if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
-    FunctionProtoTypeLoc Proto =
-    cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
-    Method->setParams(Proto.getParams());
-    CheckParmsForFunctionDef(Method->param_begin(),
-                             Method->param_end(),
-                             /*CheckParameterNames=*/false);
-    
-    // Introduce our parameters into the function scope
-    for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) {
-      ParmVarDecl *Param = Method->getParamDecl(p);
-      Param->setOwningFunction(Method);
-      
-      // If this has an identifier, add it to the scope stack.
-      if (Param->getIdentifier()) {
-        CheckShadow(CurScope, Param);
-        
-        PushOnScopeChains(Param, CurScope);
-      }
-    }
-  }
-
-  const FunctionType *Fn = MethodTy->getAs<FunctionType>();
-  QualType RetTy = Fn->getResultType();
-  if (RetTy != Context.DependentTy) {
-    LSI->ReturnType = RetTy;
-  } else {
-    LSI->HasImplicitReturnType = true;
-  }
-
-  // FIXME: Check return type is complete, !isObjCObjectType
-  
-}
-
-void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
-  // Leave the expression-evaluation context.
-  DiscardCleanupsInEvaluationContext();
-  PopExpressionEvaluationContext();
-
-  // Leave the context of the lambda.
-  PopDeclContext();
-  PopFunctionScopeInfo();
-}
-
-ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
-                                 Stmt *Body, Scope *CurScope) {
-  // Leave the expression-evaluation context.
-  DiscardCleanupsInEvaluationContext();
-  PopExpressionEvaluationContext();
-
-  // FIXME: End-of-lambda checking
-
-  // Collect information from the lambda scope.
-  llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
-  llvm::SmallVector<Expr *, 4> CaptureInits;
-  LambdaCaptureDefault CaptureDefault;
-  CXXRecordDecl *Class;
-  SourceRange IntroducerRange;
-  bool ExplicitParams;
-  {
-    LambdaScopeInfo *LSI = getCurLambda();
-    Class = LSI->Lambda;
-    IntroducerRange = LSI->IntroducerRange;
-    ExplicitParams = LSI->ExplicitParams;
-
-    // Translate captures.
-    for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
-      LambdaScopeInfo::Capture From = LSI->Captures[I];
-      assert(!From.isBlockCapture() && "Cannot capture __block variables");
-      bool IsImplicit = I >= LSI->NumExplicitCaptures;
-
-      // Handle 'this' capture.
-      if (From.isThisCapture()) {
-        Captures.push_back(LambdaExpr::Capture(From.getLocation(),
-                                               IsImplicit,
-                                               LCK_This));
-        CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
-                                                         getCurrentThisType(),
-                                                         /*isImplicit=*/true));
-        continue;
-      }
-
-      VarDecl *Var = From.getVariable();
-      // FIXME: Handle pack expansions.
-      LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
-      Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, 
-                                             Kind, Var));
-      CaptureInits.push_back(From.getCopyExpr());
-    }
-
-    switch (LSI->ImpCaptureStyle) {
-    case CapturingScopeInfo::ImpCap_None:
-      CaptureDefault = LCD_None;
-      break;
-
-    case CapturingScopeInfo::ImpCap_LambdaByval:
-      CaptureDefault = LCD_ByCopy;
-      break;
-
-    case CapturingScopeInfo::ImpCap_LambdaByref:
-      CaptureDefault = LCD_ByRef;
-      break;
-
-    case CapturingScopeInfo::ImpCap_Block:
-      llvm_unreachable("block capture in lambda");
-      break;
-    }
-
-    // C++ [expr.prim.lambda]p7:
-    //   The lambda-expression’s compound-statement yields the
-    //   function-body (8.4) of the function call operator [...].
-    ActOnFinishFunctionBody(LSI->CallOperator, Body, /*IsInstantation=*/false);
-  }
-
-  Expr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
-                                    CaptureDefault, Captures, ExplicitParams, 
-                                    CaptureInits, Body->getLocEnd());
-  (void)Lambda;
-  Diag(StartLoc, diag::err_lambda_unsupported);
-  return ExprError();
-}

Added: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=150089&view=auto
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (added)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed Feb  8 15:18:48 2012
@@ -0,0 +1,346 @@
+//===--- SemaLambda.cpp - Semantic Analysis for C++11 Lambdas -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file implements semantic analysis for C++ lambda expressions.
+//
+//===----------------------------------------------------------------------===//
+#include "clang/Sema/DeclSpec.h"
+#include "clang/Sema/Initialization.h"
+#include "clang/Sema/Lookup.h"
+#include "clang/Sema/ScopeInfo.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/AST/ExprCXX.h"
+using namespace clang;
+using namespace sema;
+
+void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
+                                        Declarator &ParamInfo,
+                                        Scope *CurScope) {
+  DeclContext *DC = CurContext;
+  while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext()))
+    DC = DC->getParent();
+
+  // Start constructing the lambda class.
+  CXXRecordDecl *Class = CXXRecordDecl::Create(Context, TTK_Class, DC,
+                                               Intro.Range.getBegin(),
+                                               /*IdLoc=*/SourceLocation(),
+                                               /*Id=*/0);
+  Class->startDefinition();
+  Class->setLambda(true);
+  CurContext->addDecl(Class);
+
+  // Build the call operator; we don't really have all the relevant information
+  // at this point, but we need something to attach child declarations to.
+  QualType MethodTy;
+  TypeSourceInfo *MethodTyInfo;
+  bool ExplicitParams = true;
+  SourceLocation EndLoc;
+  if (ParamInfo.getNumTypeObjects() == 0) {
+    // C++11 [expr.prim.lambda]p4:
+    //   If a lambda-expression does not include a lambda-declarator, it is as 
+    //   if the lambda-declarator were ().
+    FunctionProtoType::ExtProtoInfo EPI;
+    EPI.TypeQuals |= DeclSpec::TQ_const;
+    MethodTy = Context.getFunctionType(Context.DependentTy,
+                                       /*Args=*/0, /*NumArgs=*/0, EPI);
+    MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
+    ExplicitParams = false;
+    EndLoc = Intro.Range.getEnd();
+  } else {
+    assert(ParamInfo.isFunctionDeclarator() &&
+           "lambda-declarator is a function");
+    DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getFunctionTypeInfo();
+    
+    // C++11 [expr.prim.lambda]p5:
+    //   This function call operator is declared const (9.3.1) if and only if 
+    //   the lambda-expression's parameter-declaration-clause is not followed 
+    //   by mutable. It is neither virtual nor declared volatile. [...]
+    if (!FTI.hasMutableQualifier())
+      FTI.TypeQuals |= DeclSpec::TQ_const;
+    
+    // C++11 [expr.prim.lambda]p5:
+    //   [...] Default arguments (8.3.6) shall not be specified in the 
+    //   parameter-declaration-clause of a lambda-declarator.
+    CheckExtraCXXDefaultArguments(ParamInfo);
+    
+    MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
+    // FIXME: Can these asserts actually fail?
+    assert(MethodTyInfo && "no type from lambda-declarator");
+    MethodTy = MethodTyInfo->getType();
+    assert(!MethodTy.isNull() && "no type from lambda declarator");
+    EndLoc = ParamInfo.getSourceRange().getEnd();
+  }
+  
+  // C++11 [expr.prim.lambda]p5:
+  //   The closure type for a lambda-expression has a public inline function 
+  //   call operator (13.5.4) whose parameters and return type are described by
+  //   the lambda-expression's parameter-declaration-clause and 
+  //   trailing-return-type respectively.
+  DeclarationName MethodName
+    = Context.DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclarationNameLoc MethodNameLoc;
+  MethodNameLoc.CXXOperatorName.BeginOpNameLoc
+    = Intro.Range.getBegin().getRawEncoding();
+  MethodNameLoc.CXXOperatorName.EndOpNameLoc
+    = Intro.Range.getEnd().getRawEncoding();
+  CXXMethodDecl *Method
+    = CXXMethodDecl::Create(Context, Class, EndLoc,
+                            DeclarationNameInfo(MethodName, 
+                                                Intro.Range.getBegin(),
+                                                MethodNameLoc),
+                            MethodTy, MethodTyInfo,
+                            /*isStatic=*/false,
+                            SC_None,
+                            /*isInline=*/true,
+                            /*isConstExpr=*/false,
+                            EndLoc);
+  Method->setAccess(AS_public);
+  Class->addDecl(Method);
+  Method->setLexicalDeclContext(DC); // FIXME: Minor hack.
+  
+  ProcessDeclAttributes(CurScope, Method, ParamInfo);
+  
+  // Enter a new evaluation context to insulate the block from any
+  // cleanups from the enclosing full-expression.
+  PushExpressionEvaluationContext(PotentiallyEvaluated);
+  
+  PushDeclContext(CurScope, Method);
+    
+  // Introduce the lambda scope.
+  PushLambdaScope(Class, Method);
+  LambdaScopeInfo *LSI = getCurLambda();
+  if (Intro.Default == LCD_ByCopy)
+    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
+  else if (Intro.Default == LCD_ByRef)
+    LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByref;
+  LSI->IntroducerRange = Intro.Range;
+  LSI->ExplicitParams = ExplicitParams;
+  LSI->Mutable = (Method->getTypeQualifiers() & Qualifiers::Const) == 0;
+ 
+  // Handle explicit captures.
+  for (llvm::SmallVector<LambdaCapture, 4>::const_iterator
+         C = Intro.Captures.begin(), 
+         E = Intro.Captures.end(); 
+       C != E; ++C) {
+    if (C->Kind == LCK_This) {
+      // C++11 [expr.prim.lambda]p8:
+      //   An identifier or this shall not appear more than once in a 
+      //   lambda-capture.
+      if (LSI->isCXXThisCaptured()) {
+        Diag(C->Loc, diag::err_capture_more_than_once) 
+          << "'this'"
+          << SourceRange(LSI->getCXXThisCapture().getLocation());
+        continue;
+      }
+
+      // C++11 [expr.prim.lambda]p8:
+      //   If a lambda-capture includes a capture-default that is =, the 
+      //   lambda-capture shall not contain this [...].
+      if (Intro.Default == LCD_ByCopy) {
+        Diag(C->Loc, diag::err_this_capture_with_copy_default);
+        continue;
+      }
+
+      // C++11 [expr.prim.lambda]p12:
+      //   If this is captured by a local lambda expression, its nearest
+      //   enclosing function shall be a non-static member function.
+      QualType ThisCaptureType = getCurrentThisType();
+      if (ThisCaptureType.isNull()) {
+        Diag(C->Loc, diag::err_this_capture) << true;
+        continue;
+      }
+      
+      CheckCXXThisCapture(C->Loc, /*Explicit=*/true);
+      continue;
+    }
+
+    assert(C->Id && "missing identifier for capture");
+
+    // C++11 [expr.prim.lambda]p8:
+    //   If a lambda-capture includes a capture-default that is &, the 
+    //   identifiers in the lambda-capture shall not be preceded by &.
+    //   If a lambda-capture includes a capture-default that is =, [...]
+    //   each identifier it contains shall be preceded by &.
+    if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
+      Diag(C->Loc, diag::err_reference_capture_with_reference_default);
+      continue;
+    } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
+      Diag(C->Loc, diag::err_copy_capture_with_copy_default);
+      continue;
+    }
+
+    DeclarationNameInfo Name(C->Id, C->Loc);
+    LookupResult R(*this, Name, LookupOrdinaryName);
+    LookupName(R, CurScope);
+    if (R.isAmbiguous())
+      continue;
+    if (R.empty()) {
+      // FIXME: Disable corrections that would add qualification?
+      CXXScopeSpec ScopeSpec;
+      DeclFilterCCC<VarDecl> Validator;
+      if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
+        continue;
+    }
+
+    // C++11 [expr.prim.lambda]p10:
+    //   The identifiers in a capture-list are looked up using the usual rules
+    //   for unqualified name lookup (3.4.1); each such lookup shall find a 
+    //   variable with automatic storage duration declared in the reaching 
+    //   scope of the local lambda expression.
+    // FIXME: Check reaching scope. 
+    VarDecl *Var = R.getAsSingle<VarDecl>();
+    if (!Var) {
+      Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
+      continue;
+    }
+
+    if (!Var->hasLocalStorage()) {
+      Diag(C->Loc, diag::err_capture_non_automatic_variable) << C->Id;
+      Diag(Var->getLocation(), diag::note_previous_decl) << C->Id;
+      continue;
+    }
+
+    // C++11 [expr.prim.lambda]p8:
+    //   An identifier or this shall not appear more than once in a 
+    //   lambda-capture.
+    if (LSI->isCaptured(Var)) {
+      Diag(C->Loc, diag::err_capture_more_than_once) 
+        << C->Id
+        << SourceRange(LSI->getCapture(Var).getLocation());
+      continue;
+    }
+
+    TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
+                                                 TryCapture_ExplicitByVal;
+    TryCaptureVar(Var, C->Loc, Kind);
+  }
+  LSI->finishedExplicitCaptures();
+
+  // Set the parameters on the decl, if specified.
+  if (isa<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc())) {
+    FunctionProtoTypeLoc Proto =
+    cast<FunctionProtoTypeLoc>(MethodTyInfo->getTypeLoc());
+    Method->setParams(Proto.getParams());
+    CheckParmsForFunctionDef(Method->param_begin(),
+                             Method->param_end(),
+                             /*CheckParameterNames=*/false);
+    
+    // Introduce our parameters into the function scope
+    for (unsigned p = 0, NumParams = Method->getNumParams(); p < NumParams; ++p) {
+      ParmVarDecl *Param = Method->getParamDecl(p);
+      Param->setOwningFunction(Method);
+      
+      // If this has an identifier, add it to the scope stack.
+      if (Param->getIdentifier()) {
+        CheckShadow(CurScope, Param);
+        
+        PushOnScopeChains(Param, CurScope);
+      }
+    }
+  }
+
+  const FunctionType *Fn = MethodTy->getAs<FunctionType>();
+  QualType RetTy = Fn->getResultType();
+  if (RetTy != Context.DependentTy) {
+    LSI->ReturnType = RetTy;
+  } else {
+    LSI->HasImplicitReturnType = true;
+  }
+
+  // FIXME: Check return type is complete, !isObjCObjectType
+  
+}
+
+void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope) {
+  // Leave the expression-evaluation context.
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+
+  // Leave the context of the lambda.
+  PopDeclContext();
+  PopFunctionScopeInfo();
+}
+
+ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc,
+                                 Stmt *Body, Scope *CurScope) {
+  // Leave the expression-evaluation context.
+  DiscardCleanupsInEvaluationContext();
+  PopExpressionEvaluationContext();
+
+  // FIXME: End-of-lambda checking
+
+  // Collect information from the lambda scope.
+  llvm::SmallVector<LambdaExpr::Capture, 4> Captures;
+  llvm::SmallVector<Expr *, 4> CaptureInits;
+  LambdaCaptureDefault CaptureDefault;
+  CXXRecordDecl *Class;
+  SourceRange IntroducerRange;
+  bool ExplicitParams;
+  {
+    LambdaScopeInfo *LSI = getCurLambda();
+    Class = LSI->Lambda;
+    IntroducerRange = LSI->IntroducerRange;
+    ExplicitParams = LSI->ExplicitParams;
+
+    // Translate captures.
+    for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I) {
+      LambdaScopeInfo::Capture From = LSI->Captures[I];
+      assert(!From.isBlockCapture() && "Cannot capture __block variables");
+      bool IsImplicit = I >= LSI->NumExplicitCaptures;
+
+      // Handle 'this' capture.
+      if (From.isThisCapture()) {
+        Captures.push_back(LambdaExpr::Capture(From.getLocation(),
+                                               IsImplicit,
+                                               LCK_This));
+        CaptureInits.push_back(new (Context) CXXThisExpr(From.getLocation(),
+                                                         getCurrentThisType(),
+                                                         /*isImplicit=*/true));
+        continue;
+      }
+
+      VarDecl *Var = From.getVariable();
+      // FIXME: Handle pack expansions.
+      LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
+      Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, 
+                                             Kind, Var));
+      CaptureInits.push_back(From.getCopyExpr());
+    }
+
+    switch (LSI->ImpCaptureStyle) {
+    case CapturingScopeInfo::ImpCap_None:
+      CaptureDefault = LCD_None;
+      break;
+
+    case CapturingScopeInfo::ImpCap_LambdaByval:
+      CaptureDefault = LCD_ByCopy;
+      break;
+
+    case CapturingScopeInfo::ImpCap_LambdaByref:
+      CaptureDefault = LCD_ByRef;
+      break;
+
+    case CapturingScopeInfo::ImpCap_Block:
+      llvm_unreachable("block capture in lambda");
+      break;
+    }
+
+    // C++ [expr.prim.lambda]p7:
+    //   The lambda-expression's compound-statement yields the
+    //   function-body (8.4) of the function call operator [...].
+    ActOnFinishFunctionBody(LSI->CallOperator, Body, /*IsInstantation=*/false);
+  }
+
+  Expr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, 
+                                    CaptureDefault, Captures, ExplicitParams, 
+                                    CaptureInits, Body->getLocEnd());
+  (void)Lambda;
+  Diag(StartLoc, diag::err_lambda_unsupported);
+  return ExprError();
+}

Propchange: cfe/trunk/lib/Sema/SemaLambda.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/lib/Sema/SemaLambda.cpp
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cfe/trunk/lib/Sema/SemaLambda.cpp
------------------------------------------------------------------------------
    svn:mime-type = text/plain





More information about the cfe-commits mailing list