<div dir="ltr">There were a couple of unused variables in this patch that caused the Clang self-host -Werror build to fail. I've removed them in r194190 though it looks like this might allow some simplification of GetInnermostEnclosingCapturableLambda - instead of returning a pointer that's not used, perhaps you could return a boolean or an Optional<unsigned> (and move the non-const ref unsigned into the return value)<div>
<br>Also:<br><br>There's a bunch of strangely wrapped lines and trailing whitespace in this patch - it might be good to run clang-format over the bits you added and recommit (& prefer formatting before committing in the future).<br>
<br>And possibly prefer the modern LLVM naming convention of lower-first for function names ( <a href="http://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly">http://llvm.org/docs/CodingStandards.html#name-types-functions-variables-and-enumerators-properly</a> )</div>
</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Nov 6, 2013 at 9:17 PM, Faisal Vali <span dir="ltr"><<a href="mailto:faisalv@yahoo.com" target="_blank">faisalv@yahoo.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: faisalv<br>
Date: Wed Nov  6 23:17:06 2013<br>
New Revision: 194188<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=194188&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=194188&view=rev</a><br>
Log:<br>
This patch implements capturing of variables within generic lambdas.<br>
<br>
Both Richard and I felt that the current wording in the working paper needed some tweaking - Please see <a href="http://llvm-reviews.chandlerc.com/D2035" target="_blank">http://llvm-reviews.chandlerc.com/D2035</a> for additional context and references to core-reflector messages that discuss wording tweaks.<br>

<br>
What is implemented is what we had intended to specify in Bristol; but, recently felt that the specification might benefit from some tweaking and fleshing.<br>
<br>
As a rough attempt to explain the semantics: If a nested lambda with a default-capture names a variable within its body, and if the enclosing full expression that contains the name of that variable is instantiation-dependent - then an enclosing lambda that is capture-ready (i.e. within a non-dependent context) must capture that variable, if all intervening nested lambdas can potentially capture that variable if they need to, and all intervening parent lambdas of the capture-ready lambda can and do capture the variable.<br>

<br>
Of note, 'this' capturing is also currently underspecified in the working paper for generic lambdas.  What is implemented here is if the set of candidate functions in a nested generic lambda includes both static and non-static member functions (regardless of viability checking - i.e. num and type of parameters/arguments) - and if all intervening nested-inner lambdas between the capture-ready lambda and the function-call containing nested lambda can capture 'this' and if all enclosing lambdas of the capture-ready lambda can capture 'this', then 'this' is speculatively captured by that capture-ready lambda.<br>

<br>
Hopefully a paper for the C++ committee (that Richard and I had started some preliminary work on) is forthcoming.<br>
<br>
This essentially makes generic lambdas feature complete, except for known bugs. The more prominent ones (and the ones I am currently aware of) being:<br>
  - generic lambdas and init-captures are broken - but a patch that fixes this is already in the works ...<br>
  - nested variadic expansions such as:<br>
    auto K = [](auto ... OuterArgs) {<br>
      vp([=](auto ... Is) {<br>
          decltype(OuterArgs) OA = OuterArgs;<br>
          return 0;<br>
        }(5)...);<br>
      return 0;<br>
    };<br>
    auto M = K('a', ' ', 1, " -- ", 3.14);<br>
   currently cause crashes.  I think I know how to fix this (since I had done so in my initial implementation) - but it will probably take some work and back & forth with Doug and Richard.<br>
<br>
A warm thanks to all who provided feedback - and especially to Doug Gregor and Richard Smith for their pivotal guidance: their insight and prestidigitation in such matters is boundless!<br>
<br>
Now let's hope this commit doesn't upset the buildbot gods ;)<br>
<br>
Thanks!<br>
<br>
Added:<br>
    cfe/trunk/include/clang/Sema/SemaLambda.h<br>
    cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp<br>
Modified:<br>
    cfe/trunk/include/clang/AST/ASTLambda.h<br>
    cfe/trunk/include/clang/Sema/ScopeInfo.h<br>
    cfe/trunk/include/clang/Sema/Sema.h<br>
    cfe/trunk/include/clang/Sema/SemaInternal.h<br>
    cfe/trunk/lib/Sema/ScopeInfo.cpp<br>
    cfe/trunk/lib/Sema/SemaDecl.cpp<br>
    cfe/trunk/lib/Sema/SemaExpr.cpp<br>
    cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
    cfe/trunk/lib/Sema/SemaExprMember.cpp<br>
    cfe/trunk/lib/Sema/SemaLambda.cpp<br>
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp<br>
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp<br>
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp<br>
    cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/ASTLambda.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTLambda.h?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTLambda.h?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/AST/ASTLambda.h (original)<br>
+++ cfe/trunk/include/clang/AST/ASTLambda.h Wed Nov  6 23:17:06 2013<br>
@@ -65,6 +65,16 @@ inline bool isGenericLambdaCallOperatorS<br>
                                           dyn_cast<CXXMethodDecl>(DC));<br>
 }<br>
<br>
+<br>
+// This returns the parent DeclContext ensuring that the correct<br>
+// parent DeclContext is returned for Lambdas<br>
+inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) {<br>
+  if (isLambdaCallOperator(DC))<br>
+    return DC->getParent()->getParent();<br>
+  else<br>
+    return DC->getParent();<br>
+}<br>
+<br>
 } // clang<br>
<br>
 #endif // LLVM_CLANG_AST_LAMBDA_H<br>
<br>
Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)<br>
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Wed Nov  6 23:17:06 2013<br>
@@ -18,8 +18,11 @@<br>
 #include "clang/AST/Type.h"<br>
 #include "clang/Basic/CapturedStmt.h"<br>
 #include "clang/Basic/PartialDiagnostic.h"<br>
+#include "clang/Sema/Ownership.h"<br>
 #include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/SmallSet.h"<br>
 #include "llvm/ADT/SmallVector.h"<br>
+#include <algorithm><br>
<br>
 namespace clang {<br>
<br>
@@ -39,6 +42,7 @@ class TemplateTypeParmDecl;<br>
 class TemplateParameterList;<br>
 class VarDecl;<br>
 class DeclRefExpr;<br>
+class MemberExpr;<br>
 class ObjCIvarRefExpr;<br>
 class ObjCPropertyRefExpr;<br>
 class ObjCMessageExpr;<br>
@@ -614,13 +618,36 @@ public:<br>
   /// list has been created (from the AutoTemplateParams) then<br>
   /// store a reference to it (cache it to avoid reconstructing it).<br>
   TemplateParameterList *GLTemplateParameterList;<br>
+<br>
+  /// \brief Contains all variable-referring-expressions (i.e. DeclRefExprs<br>
+  ///  or MemberExprs) that refer to local variables in a generic lambda<br>
+  ///  or a lambda in a potentially-evaluated-if-used context.<br>
+  ///<br>
+  ///  Potentially capturable variables of a nested lambda that might need<br>
+  ///   to be captured by the lambda are housed here.<br>
+  ///  This is specifically useful for generic lambdas or<br>
+  ///  lambdas within a a potentially evaluated-if-used context.<br>
+  ///  If an enclosing variable is named in an expression of a lambda nested<br>
+  ///  within a generic lambda, we don't always know know whether the variable<br>
+  ///  will truly be odr-used (i.e. need to be captured) by that nested lambda,<br>
+  ///  until its instantiation. But we still need to capture it in the<br>
+  ///  enclosing lambda if all intervening lambdas can capture the variable.<br>
+<br>
+  llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs;<br>
+<br>
+  /// \brief Contains all variable-referring-expressions that refer<br>
+  ///  to local variables that are usable as constant expressions and<br>
+  ///  do not involve an odr-use (they may still need to be captured<br>
+  ///  if the enclosing full-expression is instantiation dependent).<br>
+  llvm::SmallSet<Expr*, 8> NonODRUsedCapturingExprs;<br>
+<br>
+  SourceLocation PotentialThisCaptureLocation;<br>
<br>
   LambdaScopeInfo(DiagnosticsEngine &Diag)<br>
     : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0),<br>
       CallOperator(0), NumExplicitCaptures(0), Mutable(false),<br>
       ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false),<br>
-      AutoTemplateParameterDepth(0),<br>
-      GLTemplateParameterList(0)<br>
+      AutoTemplateParameterDepth(0), GLTemplateParameterList(0)<br>
   {<br>
     Kind = SK_Lambda;<br>
   }<br>
@@ -635,6 +662,110 @@ public:<br>
   static bool classof(const FunctionScopeInfo *FSI) {<br>
     return FSI->Kind == SK_Lambda;<br>
   }<br>
+<br>
+  ///<br>
+  /// \brief Add a variable that might potentially be captured by the<br>
+  /// lambda and therefore the enclosing lambdas.<br>
+  ///<br>
+  /// This is also used by enclosing lambda's to speculatively capture<br>
+  /// variables that nested lambda's - depending on their enclosing<br>
+  /// specialization - might need to capture.<br>
+  /// Consider:<br>
+  /// void f(int, int); <-- don't capture<br>
+  /// void f(const int&, double); <-- capture<br>
+  /// void foo() {<br>
+  ///   const int x = 10;<br>
+  ///   auto L = [=](auto a) { // capture 'x'<br>
+  ///      return [=](auto b) {<br>
+  ///        f(x, a);  // we may or may not need to capture 'x'<br>
+  ///      };<br>
+  ///   };<br>
+  /// }<br>
+  void addPotentialCapture(Expr *VarExpr) {<br>
+    assert(isa<DeclRefExpr>(VarExpr) || isa<MemberExpr>(VarExpr));<br>
+    PotentiallyCapturingExprs.push_back(VarExpr);<br>
+  }<br>
+<br>
+  void addPotentialThisCapture(SourceLocation Loc) {<br>
+    PotentialThisCaptureLocation = Loc;<br>
+  }<br>
+  bool hasPotentialThisCapture() const {<br>
+    return PotentialThisCaptureLocation.isValid();<br>
+  }<br>
+<br>
+  /// \brief Mark a variable's reference in a lambda as non-odr using.<br>
+  ///<br>
+  /// For generic lambdas, if a variable is named in a potentially evaluated<br>
+  /// expression, where the enclosing full expression is dependent then we<br>
+  /// must capture the variable (given a default capture).<br>
+  /// This is accomplished by recording all references to variables<br>
+  /// (DeclRefExprs or MemberExprs) within said nested lambda in its array of<br>
+  /// PotentialCaptures. All such variables have to be captured by that lambda,<br>
+  /// except for as described below.<br>
+  /// If that variable is usable as a constant expression and is named in a<br>
+  /// manner that does not involve its odr-use (e.g. undergoes<br>
+  /// lvalue-to-rvalue conversion, or discarded) record that it is so. Upon the<br>
+  /// act of analyzing the enclosing full expression (ActOnFinishFullExpr)<br>
+  /// if we can determine that the full expression is not instantiation-<br>
+  /// dependent, then we can entirely avoid its capture.<br>
+  ///<br>
+  ///   const int n = 0;<br>
+  ///   [&] (auto x) {<br>
+  ///     (void)+n + x;<br>
+  ///   };<br>
+  /// Interestingly, this strategy would involve a capture of n, even though<br>
+  /// it's obviously not odr-used here, because the full-expression is<br>
+  /// instantiation-dependent.  It could be useful to avoid capturing such<br>
+  /// variables, even when they are referred to in an instantiation-dependent<br>
+  /// expression, if we can unambiguously determine that they shall never be<br>
+  /// odr-used.  This would involve removal of the variable-referring-expression<br>
+  /// from the array of PotentialCaptures during the lvalue-to-rvalue<br>
+  /// conversions.  But per the working draft N3797, (post-chicago 2013) we must<br>
+  /// capture such variables.<br>
+  /// Before anyone is tempted to implement a strategy for not-capturing 'n',<br>
+  /// consider the insightful warning in:<br>
+  ///    /cfe-commits/Week-of-Mon-20131104/092596.html<br>
+  /// "The problem is that the set of captures for a lambda is part of the ABI<br>
+  ///  (since lambda layout can be made visible through inline functions and the<br>
+  ///  like), and there are no guarantees as to which cases we'll manage to build<br>
+  ///  an lvalue-to-rvalue conversion in, when parsing a template -- some<br>
+  ///  seemingly harmless change elsewhere in Sema could cause us to start or stop<br>
+  ///  building such a node. So we need a rule that anyone can implement and get<br>
+  ///  exactly the same result".<br>
+  ///<br>
+  void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) {<br>
+    assert(isa<DeclRefExpr>(CapturingVarExpr)<br>
+        || isa<MemberExpr>(CapturingVarExpr));<br>
+    NonODRUsedCapturingExprs.insert(CapturingVarExpr);<br>
+  }<br>
+  bool isVariableExprMarkedAsNonODRUsed(Expr *CapturingVarExpr) {<br>
+    assert(isa<DeclRefExpr>(CapturingVarExpr)<br>
+      || isa<MemberExpr>(CapturingVarExpr));<br>
+    return NonODRUsedCapturingExprs.count(CapturingVarExpr);<br>
+  }<br>
+  void removePotentialCapture(Expr *E) {<br>
+    PotentiallyCapturingExprs.erase(<br>
+        std::remove(PotentiallyCapturingExprs.begin(),<br>
+            PotentiallyCapturingExprs.end(), E),<br>
+        PotentiallyCapturingExprs.end());<br>
+  }<br>
+  void clearPotentialCaptures() {<br>
+    PotentiallyCapturingExprs.clear();<br>
+    PotentialThisCaptureLocation = SourceLocation();<br>
+  }<br>
+  unsigned getNumPotentialVariableCaptures() const {<br>
+    return PotentiallyCapturingExprs.size();<br>
+  }<br>
+<br>
+  bool hasPotentialCaptures() const {<br>
+    return getNumPotentialVariableCaptures() ||<br>
+                                  PotentialThisCaptureLocation.isValid();<br>
+  }<br>
+<br>
+  // When passed the index, returns the VarDecl and Expr associated<br>
+  // with the index.<br>
+  void getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E);<br>
+<br>
 };<br>
<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Nov  6 23:17:06 2013<br>
@@ -3155,12 +3155,19 @@ public:<br>
   /// from within the current scope. Only valid when the variable can be<br>
   /// captured.<br>
   ///<br>
+  /// \param FunctionScopeIndexToStopAt If non-null, it points to the index<br>
+  /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.<br>
+  /// This is useful when enclosing lambdas must speculatively capture<br>
+  /// variables that may or may not be used in certain specializations of<br>
+  /// a nested generic lambda.<br>
+  ///<br>
   /// \returns true if an error occurred (i.e., the variable cannot be<br>
   /// captured) and false if the capture succeeded.<br>
   bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind,<br>
                           SourceLocation EllipsisLoc, bool BuildAndDiagnose,<br>
                           QualType &CaptureType,<br>
-                          QualType &DeclRefType);<br>
+                          QualType &DeclRefType,<br>
+                          const unsigned *const FunctionScopeIndexToStopAt);<br>
<br>
   /// \brief Try to capture the given variable.<br>
   bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc,<br>
@@ -4082,7 +4089,17 @@ public:<br>
   ///<br>
   /// \param Explicit Whether 'this' is explicitly captured in a lambda<br>
   /// capture list.<br>
-  void CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false);<br>
+  ///<br>
+  /// \param FunctionScopeIndexToStopAt If non-null, it points to the index<br>
+  /// of the FunctionScopeInfo stack beyond which we do not attempt to capture.<br>
+  /// This is useful when enclosing lambdas must speculatively capture<br>
+  /// 'this' that may or may not be used in certain specializations of<br>
+  /// a nested generic lambda (depending on whether the name resolves to<br>
+  /// a non-static member function or a static function).<br>
+  /// \return returns 'true' if failed, 'false' if success.<br>
+  bool CheckCXXThisCapture(SourceLocation Loc, bool Explicit = false,<br>
+      bool BuildAndDiagnose = true,<br>
+      const unsigned *const FunctionScopeIndexToStopAt = 0);<br>
<br>
   /// \brief Determine whether the given type is the type of *this that is used<br>
   /// outside of the body of a member function for a type that is currently<br>
<br>
Modified: cfe/trunk/include/clang/Sema/SemaInternal.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaInternal.h?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaInternal.h?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/SemaInternal.h (original)<br>
+++ cfe/trunk/include/clang/Sema/SemaInternal.h Wed Nov  6 23:17:06 2013<br>
@@ -24,7 +24,44 @@ namespace clang {<br>
 inline PartialDiagnostic Sema::PDiag(unsigned DiagID) {<br>
   return PartialDiagnostic(DiagID, Context.getDiagAllocator());<br>
 }<br>
-<br>
+<br>
+<br>
+// This requires the variable to be non-dependent and the initializer<br>
+// to not be value dependent.<br>
+inline bool IsVariableAConstantExpression(VarDecl *Var, ASTContext &Context) {<br>
+  const VarDecl *DefVD = 0;<br>
+  return !isa<ParmVarDecl>(Var) &&<br>
+    Var->isUsableInConstantExpressions(Context) &&<br>
+    Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE();<br>
+}<br>
+<br>
+// Directly mark a variable odr-used. Given a choice, prefer to use<br>
+// MarkVariableReferenced since it does additional checks and then<br>
+// calls MarkVarDeclODRUsed.<br>
+// If the variable must be captured:<br>
+//  - if FunctionScopeIndexToStopAt is null, capture it in the CurContext<br>
+//  - else capture it in the DeclContext that maps to the<br>
+//    *FunctionScopeIndexToStopAt on the FunctionScopeInfo stack.<br>
+inline void MarkVarDeclODRUsed(VarDecl *Var,<br>
+    SourceLocation Loc, Sema &SemaRef,<br>
+    const unsigned *const FunctionScopeIndexToStopAt) {<br>
+  // Keep track of used but undefined variables.<br>
+  // FIXME: We shouldn't suppress this warning for static data members.<br>
+  if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&<br>
+    !Var->isExternallyVisible() &&<br>
+    !(Var->isStaticDataMember() && Var->hasInit())) {<br>
+      SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];<br>
+      if (old.isInvalid()) old = Loc;<br>
+  }<br>
+  QualType CaptureType, DeclRefType;<br>
+  SemaRef.tryCaptureVariable(Var, Loc, Sema::TryCapture_Implicit,<br>
+    /*EllipsisLoc*/ SourceLocation(),<br>
+    /*BuildAndDiagnose*/ true,<br>
+    CaptureType, DeclRefType,<br>
+    FunctionScopeIndexToStopAt);<br>
+<br>
+  Var->markUsed(SemaRef.Context);<br>
+}<br>
 }<br>
<br>
 #endif<br>
<br>
Added: cfe/trunk/include/clang/Sema/SemaLambda.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaLambda.h?rev=194188&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaLambda.h?rev=194188&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/SemaLambda.h (added)<br>
+++ cfe/trunk/include/clang/Sema/SemaLambda.h Wed Nov  6 23:17:06 2013<br>
@@ -0,0 +1,39 @@<br>
+//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+///<br>
+/// \file<br>
+/// \brief This file provides some common utility functions for processing<br>
+/// Lambdas.<br>
+///<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#ifndef LLVM_CLANG_SEMA_LAMBDA_H<br>
+#define LLVM_CLANG_SEMA_LAMBDA_H<br>
+#include "clang/AST/ASTLambda.h"<br>
+#include "clang/Sema/ScopeInfo.h"<br>
+namespace clang {<br>
+<br>
+// Given a lambda's call operator and a variable (or null for 'this'),<br>
+// compute the nearest enclosing lambda that is capture-ready (i.e<br>
+// the enclosing context is not dependent, and all intervening lambdas can<br>
+// either implicitly or explicitly capture Var)<br>
+//<br>
+// Return the CallOperator of the capturable lambda and set function scope<br>
+// index to the correct index within the function scope stack to correspond<br>
+// to the capturable lambda.<br>
+// If VarDecl *VD is null, we check for 'this' capture.<br>
+CXXMethodDecl*<br>
+GetInnermostEnclosingCapturableLambda(<br>
+    ArrayRef<sema::FunctionScopeInfo*> FunctionScopes,<br>
+    unsigned &FunctionScopeIndex,<br>
+    DeclContext *const CurContext, VarDecl *VD, Sema &S);<br>
+<br>
+} // clang<br>
+<br>
+#endif // LLVM_CLANG_SEMA_LAMBDA_H<br>
<br>
Modified: cfe/trunk/lib/Sema/ScopeInfo.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ScopeInfo.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ScopeInfo.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/ScopeInfo.cpp (original)<br>
+++ cfe/trunk/lib/Sema/ScopeInfo.cpp Wed Nov  6 23:17:06 2013<br>
@@ -184,6 +184,21 @@ void FunctionScopeInfo::markSafeWeakUse(<br>
   ThisUse->markSafe();<br>
 }<br>
<br>
+void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD, Expr *&E) {<br>
+  assert((Idx >= 0 && Idx < getNumPotentialVariableCaptures()) &&<br>
+    "Index of potential capture must be within 0 to less than the "<br>
+    "number of captures!");<br>
+  E = PotentiallyCapturingExprs[Idx];<br>
+  if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))<br>
+    VD = dyn_cast<VarDecl>(DRE->getFoundDecl());<br>
+  else if (MemberExpr *ME = dyn_cast<MemberExpr>(E))<br>
+    VD = dyn_cast<VarDecl>(ME->getMemberDecl());<br>
+  else<br>
+    llvm_unreachable("Only DeclRefExprs or MemberExprs should be added for "<br>
+    "potential captures");<br>
+  assert(VD);<br>
+}<br>
+<br>
 FunctionScopeInfo::~FunctionScopeInfo() { }<br>
 BlockScopeInfo::~BlockScopeInfo() { }<br>
 LambdaScopeInfo::~LambdaScopeInfo() { }<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Nov  6 23:17:06 2013<br>
@@ -40,6 +40,7 @@<br>
 #include "clang/Sema/ParsedTemplate.h"<br>
 #include "clang/Sema/Scope.h"<br>
 #include "clang/Sema/ScopeInfo.h"<br>
+#include "clang/Sema/Template.h"<br>
 #include "llvm/ADT/SmallString.h"<br>
 #include "llvm/ADT/Triple.h"<br>
 #include <algorithm><br>
@@ -9428,6 +9429,8 @@ Sema::CheckForFunctionRedefinition(Funct<br>
   Diag(Definition->getLocation(), diag::note_previous_definition);<br>
   FD->setInvalidDecl();<br>
 }<br>
+<br>
+<br>
 static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,<br>
                                    Sema &S) {<br>
   CXXRecordDecl *const LambdaClass = CallOperator->getParent();<br>
@@ -9449,7 +9452,27 @@ static void RebuildLambdaScopeInfo(CXXMe<br>
   LSI->IntroducerRange = DNI.getCXXOperatorNameRange();<br>
   LSI->Mutable = !CallOperator->isConst();<br>
<br>
-  // FIXME: Add the captures to the LSI.<br>
+  // Add the captures to the LSI so they can be noted as already<br>
+  // captured within tryCaptureVar.<br>
+  for (LambdaExpr::capture_iterator C = LambdaClass->captures_begin(),<br>
+      CEnd = LambdaClass->captures_end(); C != CEnd; ++C) {<br>
+    if (C->capturesVariable()) {<br>
+      VarDecl *VD = C->getCapturedVar();<br>
+      if (VD->isInitCapture())<br>
+        S.CurrentInstantiationScope->InstantiatedLocal(VD, VD);<br>
+      QualType CaptureType = VD->getType();<br>
+      const bool ByRef = C->getCaptureKind() == LCK_ByRef;<br>
+      LSI->addCapture(VD, /*IsBlock*/false, ByRef,<br>
+          /*RefersToEnclosingLocal*/true, C->getLocation(),<br>
+          /*EllipsisLoc*/C->isPackExpansion()<br>
+                         ? C->getEllipsisLoc() : SourceLocation(),<br>
+          CaptureType, /*Expr*/ 0);<br>
+<br>
+    } else if (C->capturesThis()) {<br>
+      LSI->addThisCapture(/*Nested*/ false, C->getLocation(),<br>
+                              S.getCurrentThisType(), /*Expr*/ 0);<br>
+    }<br>
+  }<br>
 }<br>
<br>
 Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Nov  6 23:17:06 2013<br>
@@ -15,6 +15,7 @@<br>
 #include "TreeTransform.h"<br>
 #include "clang/AST/ASTConsumer.h"<br>
 #include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/ASTLambda.h"<br>
 #include "clang/AST/ASTMutationListener.h"<br>
 #include "clang/AST/CXXInheritance.h"<br>
 #include "clang/AST/DeclObjC.h"<br>
@@ -11374,12 +11375,8 @@ static bool isVariableAlreadyCapturedInS<br>
 static DeclContext *getParentOfCapturingContextOrNull(DeclContext *DC, VarDecl *Var,<br>
                                  SourceLocation Loc,<br>
                                  const bool Diagnose, Sema &S) {<br>
-  if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC))<br>
-    return DC->getParent();<br>
-  else if (isa<CXXMethodDecl>(DC) &&<br>
-                cast<CXXMethodDecl>(DC)->getOverloadedOperator() == OO_Call &&<br>
-                cast<CXXRecordDecl>(DC->getParent())->isLambda())<br>
-    return DC->getParent()->getParent();<br>
+  if (isa<BlockDecl>(DC) || isa<CapturedDecl>(DC) || isLambdaCallOperator(DC))<br>
+    return getLambdaAwareParentOfDeclContext(DC);<br>
   else {<br>
     if (Diagnose)<br>
        diagnoseUncapturableValueReference(S, Loc, Var, DC);<br>
@@ -11815,12 +11812,24 @@ bool Sema::tryCaptureVariable(VarDecl *V<br>
                               TryCaptureKind Kind, SourceLocation EllipsisLoc,<br>
                               bool BuildAndDiagnose,<br>
                               QualType &CaptureType,<br>
-                              QualType &DeclRefType) {<br>
+                              QualType &DeclRefType,<br>
+                                                               const unsigned *const FunctionScopeIndexToStopAt) {<br>
   bool Nested = false;<br>
<br>
   DeclContext *DC = CurContext;<br>
-  const unsigned MaxFunctionScopesIndex = FunctionScopes.size() - 1;<br>
+  const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt<br>
+      ? *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;<br>
+  // We need to sync up the Declaration Context with the<br>
+  // FunctionScopeIndexToStopAt<br>
+  if (FunctionScopeIndexToStopAt) {<br>
+    unsigned FSIndex = FunctionScopes.size() - 1;<br>
+    while (FSIndex != MaxFunctionScopesIndex) {<br>
+      DC = getLambdaAwareParentOfDeclContext(DC);<br>
+      --FSIndex;<br>
+    }<br>
+  }<br>
<br>
+<br>
   // If the variable is declared in the current context (and is not an<br>
   // init-capture), there is no need to capture it.<br>
   if (!Var->isInitCapture() && Var->getDeclContext() == DC) return true;<br>
@@ -11855,7 +11864,23 @@ bool Sema::tryCaptureVariable(VarDecl *V<br>
     if (isVariableAlreadyCapturedInScopeInfo(CSI, Var, Nested, CaptureType,<br>
                                              DeclRefType))<br>
       break;<br>
-<br>
+    // If we are instantiating a generic lambda call operator body,<br>
+    // we do not want to capture new variables.  What was captured<br>
+    // during either a lambdas transformation or initial parsing<br>
+    // should be used.<br>
+    if (isGenericLambdaCallOperatorSpecialization(DC)) {<br>
+      if (BuildAndDiagnose) {<br>
+        LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(CSI);<br>
+        if (LSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_None) {<br>
+          Diag(ExprLoc, diag::err_lambda_impcap) << Var->getDeclName();<br>
+          Diag(Var->getLocation(), diag::note_previous_decl)<br>
+             << Var->getDeclName();<br>
+          Diag(LSI->Lambda->getLocStart(), diag::note_lambda_decl);<br>
+        } else<br>
+          diagnoseUncapturableValueReference(*this, ExprLoc, Var, DC);<br>
+      }<br>
+      return true;<br>
+    }<br>
     // Certain capturing entities (lambdas, blocks etc.) are not allowed to capture<br>
     // certain types of variables (unnamed, variably modified types etc.)<br>
     // so check for eligibility.<br>
@@ -11871,6 +11896,17 @@ bool Sema::tryCaptureVariable(VarDecl *V<br>
           << Var->getDeclName();<br>
         Diag(cast<LambdaScopeInfo>(CSI)->Lambda->getLocStart(),<br>
              diag::note_lambda_decl);<br>
+        // FIXME: If we error out because an outer lambda can not implicitly<br>
+        // capture a variable that an inner lambda explicitly captures, we<br>
+        // should have the inner lambda do the explicit capture - because<br>
+        // it makes for cleaner diagnostics later.  This would purely be done<br>
+        // so that the diagnostic does not misleadingly claim that a variable<br>
+        // can not be captured by a lambda implicitly even though it is captured<br>
+        // explicitly.  Suggestion:<br>
+        //  - create const bool VariableCaptureWasInitiallyExplicit = Explicit<br>
+        //    at the function head<br>
+        //  - cache the StartingDeclContext - this must be a lambda<br>
+        //  - captureInLambda in the innermost lambda the variable.<br>
       }<br>
       return true;<br>
     }<br>
@@ -11920,7 +11956,7 @@ bool Sema::tryCaptureVariable(VarDecl *V<br>
   QualType DeclRefType;<br>
   return tryCaptureVariable(Var, Loc, Kind, EllipsisLoc,<br>
                             /*BuildAndDiagnose=*/true, CaptureType,<br>
-                            DeclRefType);<br>
+                            DeclRefType, 0);<br>
 }<br>
<br>
 QualType Sema::getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc) {<br>
@@ -11929,28 +11965,36 @@ QualType Sema::getCapturedDeclRefType(Va<br>
<br>
   // Determine whether we can capture this variable.<br>
   if (tryCaptureVariable(Var, Loc, TryCapture_Implicit, SourceLocation(),<br>
-                         /*BuildAndDiagnose=*/false, CaptureType, DeclRefType))<br>
+                         /*BuildAndDiagnose=*/false, CaptureType,<br>
+                         DeclRefType, 0))<br>
     return QualType();<br>
<br>
   return DeclRefType;<br>
 }<br>
<br>
-static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var,<br>
-                               SourceLocation Loc) {<br>
-  // Keep track of used but undefined variables.<br>
-  // FIXME: We shouldn't suppress this warning for static data members.<br>
-  if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&<br>
-      !Var->isExternallyVisible() &&<br>
-      !(Var->isStaticDataMember() && Var->hasInit())) {<br>
-    SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];<br>
-    if (old.isInvalid()) old = Loc;<br>
-  }<br>
<br>
-  SemaRef.tryCaptureVariable(Var, Loc);<br>
<br>
-  Var->markUsed(SemaRef.Context);<br>
+// If either the type of the variable or the initializer is dependent,<br>
+// return false. Otherwise, determine whether the variable is a constant<br>
+// expression. Use this if you need to know if a variable that might or<br>
+// might not be dependent is truly a constant expression.<br>
+static inline bool IsVariableNonDependentAndAConstantExpression(VarDecl *Var,<br>
+    ASTContext &Context) {<br>
+<br>
+  if (Var->getType()->isDependentType())<br>
+    return false;<br>
+  const VarDecl *DefVD = 0;<br>
+  Var->getAnyInitializer(DefVD);<br>
+  if (!DefVD)<br>
+    return false;<br>
+  EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt();<br>
+  Expr *Init = cast<Expr>(Eval->Value);<br>
+  if (Init->isValueDependent())<br>
+    return false;<br>
+  return IsVariableAConstantExpression(Var, Context);<br>
 }<br>
<br>
+<br>
 void Sema::UpdateMarkingForLValueToRValue(Expr *E) {<br>
   // Per C++11 [basic.def.odr], a variable is odr-used "unless it is<br>
   // an object that satisfies the requirements for appearing in a<br>
@@ -11958,6 +12002,22 @@ void Sema::UpdateMarkingForLValueToRValu<br>
   // is immediately applied."  This function handles the lvalue-to-rvalue<br>
   // conversion part.<br>
   MaybeODRUseExprs.erase(E->IgnoreParens());<br>
+<br>
+  // If we are in a lambda, check if this DeclRefExpr or MemberExpr refers<br>
+  // to a variable that is a constant expression, and if so, identify it as<br>
+  // a reference to a variable that does not involve an odr-use of that<br>
+  // variable.<br>
+  if (LambdaScopeInfo *LSI = getCurLambda()) {<br>
+    Expr *SansParensExpr = E->IgnoreParens();<br>
+    VarDecl *Var = 0;<br>
+    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SansParensExpr))<br>
+      Var = dyn_cast<VarDecl>(DRE->getFoundDecl());<br>
+    else if (MemberExpr *ME = dyn_cast<MemberExpr>(SansParensExpr))<br>
+      Var = dyn_cast<VarDecl>(ME->getMemberDecl());<br>
+<br>
+    if (Var && IsVariableNonDependentAndAConstantExpression(Var, Context))<br>
+      LSI->markVariableExprAsNonODRUsed(SansParensExpr);<br>
+  }<br>
 }<br>
<br>
 ExprResult Sema::ActOnConstantExpression(ExprResult Res) {<br>
@@ -11988,20 +12048,56 @@ void Sema::CleanupVarDeclMarking() {<br>
       llvm_unreachable("Unexpcted expression");<br>
     }<br>
<br>
-    MarkVarDeclODRUsed(*this, Var, Loc);<br>
+    MarkVarDeclODRUsed(Var, Loc, *this, /*MaxFunctionScopeIndex Pointer*/ 0);<br>
   }<br>
<br>
   MaybeODRUseExprs.clear();<br>
 }<br>
<br>
-// Mark a VarDecl referenced, and perform the necessary handling to compute<br>
-// odr-uses.<br>
+<br>
 static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,<br>
                                     VarDecl *Var, Expr *E) {<br>
+  assert(!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)<br>
+    && "Invalid Expr argument to DoMarkVarDeclReferenced");<br>
   Var->setReferenced();<br>
<br>
-  if (!IsPotentiallyEvaluatedContext(SemaRef))<br>
-    return;<br>
+  // If the context is not PotentiallyEvaluated and not Unevaluated<br>
+  // (i.e PotentiallyEvaluatedIfUsed) do not bother to consider variables<br>
+  // in this context for odr-use unless we are within a lambda.<br>
+  // If we don't know whether the context is potentially evaluated or not<br>
+  // (for e.g., if we're in a generic lambda), we want to add a potential<br>
+  // capture and eventually analyze for odr-use.<br>
+  // We should also be able to analyze certain constructs in a non-generic<br>
+  // lambda setting for potential odr-use and capture violation:<br>
+  // template<class T> void foo(T t) {<br>
+  //    auto L = [](int i) { return t; };<br>
+  // }<br>
+  //<br>
+  if (!IsPotentiallyEvaluatedContext(SemaRef)) {<br>
+<br>
+    if (SemaRef.isUnevaluatedContext()) return;<br>
+<br>
+    const bool refersToEnclosingScope =<br>
+      (SemaRef.CurContext != Var->getDeclContext() &&<br>
+           Var->getDeclContext()->isFunctionOrMethod());<br>
+    if (!refersToEnclosingScope) return;<br>
+<br>
+    if (LambdaScopeInfo *const LSI = SemaRef.getCurLambda()) {<br>
+      // If a variable could potentially be odr-used, defer marking it so<br>
+      // until we finish analyzing the full expression for any lvalue-to-rvalue<br>
+      // or discarded value conversions that would obviate odr-use.<br>
+      // Add it to the list of potential captures that will be analyzed<br>
+      // later (ActOnFinishFullExpr) for eventual capture and odr-use marking<br>
+      // unless the variable is a reference that was initialized by a constant<br>
+      // expression (this will never need to be captured or odr-used).<br>
+      const bool IsConstantExpr = IsVariableNonDependentAndAConstantExpression(<br>
+          Var, SemaRef.Context);<br>
+      assert(E && "Capture variable should be used in an expression.");<br>
+      if (!IsConstantExpr || !Var->getType()->isReferenceType())<br>
+        LSI->addPotentialCapture(E->IgnoreParens());<br>
+    }<br>
+    return;<br>
+  }<br>
<br>
   VarTemplateSpecializationDecl *VarSpec =<br>
       dyn_cast<VarTemplateSpecializationDecl>(Var);<br>
@@ -12051,7 +12147,6 @@ static void DoMarkVarDeclReferenced(Sema<br>
       }<br>
     }<br>
   }<br>
-<br>
   // Per C++11 [basic.def.odr], a variable is odr-used "unless it satisfies<br>
   // the requirements for appearing in a constant expression (5.19) and, if<br>
   // it is an object, the lvalue-to-rvalue conversion (4.1)<br>
@@ -12060,14 +12155,16 @@ static void DoMarkVarDeclReferenced(Sema<br>
   // Note that we use the C++11 definition everywhere because nothing in<br>
   // C++03 depends on whether we get the C++03 version correct. The second<br>
   // part does not apply to references, since they are not objects.<br>
-  const VarDecl *DefVD;<br>
-  if (E && !isa<ParmVarDecl>(Var) &&<br>
-      Var->isUsableInConstantExpressions(SemaRef.Context) &&<br>
-      Var->getAnyInitializer(DefVD) && DefVD->checkInitIsICE()) {<br>
+  if (E && IsVariableAConstantExpression(Var, SemaRef.Context)) {<br>
+    // A reference initialized by a constant expression can never be<br>
+    // odr-used, so simply ignore it.<br>
+    // But a non-reference might get odr-used if it doesn't undergo<br>
+    // an lvalue-to-rvalue or is discarded, so track it.<br>
     if (!Var->getType()->isReferenceType())<br>
       SemaRef.MaybeODRUseExprs.insert(E);<br>
-  } else<br>
-    MarkVarDeclODRUsed(SemaRef, Var, Loc);<br>
+  }<br>
+  else<br>
+    MarkVarDeclODRUsed(Var, Loc, SemaRef, /*MaxFunctionScopeIndex ptr*/0);<br>
 }<br>
<br>
 /// \brief Mark a variable referenced, and check whether it is odr-used<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Nov  6 23:17:06 2013<br>
@@ -21,6 +21,7 @@<br>
 #include "clang/AST/EvaluatedExprVisitor.h"<br>
 #include "clang/AST/ExprCXX.h"<br>
 #include "clang/AST/ExprObjC.h"<br>
+#include "clang/AST/RecursiveASTVisitor.h"<br>
 #include "clang/AST/TypeLoc.h"<br>
 #include "clang/Basic/PartialDiagnostic.h"<br>
 #include "clang/Basic/TargetInfo.h"<br>
@@ -31,6 +32,7 @@<br>
 #include "clang/Sema/ParsedTemplate.h"<br>
 #include "clang/Sema/Scope.h"<br>
 #include "clang/Sema/ScopeInfo.h"<br>
+#include "clang/Sema/SemaLambda.h"<br>
 #include "clang/Sema/TemplateDeduction.h"<br>
 #include "llvm/ADT/APInt.h"<br>
 #include "llvm/ADT/STLExtras.h"<br>
@@ -751,21 +753,30 @@ static Expr *captureThis(ASTContext &Con<br>
   return new (Context) CXXThisExpr(Loc, ThisTy, /*isImplicit*/true);<br>
 }<br>
<br>
-void Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit) {<br>
+bool Sema::CheckCXXThisCapture(SourceLocation Loc, bool Explicit,<br>
+    bool BuildAndDiagnose, const unsigned *const FunctionScopeIndexToStopAt) {<br>
   // We don't need to capture this in an unevaluated context.<br>
   if (isUnevaluatedContext() && !Explicit)<br>
-    return;<br>
+    return true;<br>
<br>
-  // Otherwise, check that we can capture 'this'.<br>
+  const unsigned MaxFunctionScopesIndex = FunctionScopeIndexToStopAt ?<br>
+    *FunctionScopeIndexToStopAt : FunctionScopes.size() - 1;<br>
+ // Otherwise, check that we can capture 'this'.<br>
   unsigned NumClosures = 0;<br>
-  for (unsigned idx = FunctionScopes.size() - 1; idx != 0; idx--) {<br>
+  for (unsigned idx = MaxFunctionScopesIndex; idx != 0; idx--) {<br>
     if (CapturingScopeInfo *CSI =<br>
             dyn_cast<CapturingScopeInfo>(FunctionScopes[idx])) {<br>
       if (CSI->CXXThisCaptureIndex != 0) {<br>
         // 'this' is already being captured; there isn't anything more to do.<br>
         break;<br>
       }<br>
-<br>
+      LambdaScopeInfo *LSI = dyn_cast<LambdaScopeInfo>(CSI);<br>
+      if (LSI && isGenericLambdaCallOperatorSpecialization(LSI->CallOperator)) {<br>
+        // This context can't implicitly capture 'this'; fail out.<br>
+        if (BuildAndDiagnose)<br>
+          Diag(Loc, diag::err_this_capture) << Explicit;<br>
+        return true;<br>
+      }<br>
       if (CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByref ||<br>
           CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_LambdaByval ||<br>
           CSI->ImpCaptureStyle == CapturingScopeInfo::ImpCap_Block ||<br>
@@ -777,17 +788,18 @@ void Sema::CheckCXXThisCapture(SourceLoc<br>
         continue;<br>
       }<br>
       // This context can't implicitly capture 'this'; fail out.<br>
-      Diag(Loc, diag::err_this_capture) << Explicit;<br>
-      return;<br>
+      if (BuildAndDiagnose)<br>
+        Diag(Loc, diag::err_this_capture) << Explicit;<br>
+      return true;<br>
     }<br>
     break;<br>
   }<br>
-<br>
+  if (!BuildAndDiagnose) return false;<br>
   // Mark that we're implicitly capturing 'this' in all the scopes we skipped.<br>
   // FIXME: We need to delay this marking in PotentiallyPotentiallyEvaluated<br>
   // contexts.<br>
-  for (unsigned idx = FunctionScopes.size() - 1;<br>
-       NumClosures; --idx, --NumClosures) {<br>
+  for (unsigned idx = MaxFunctionScopesIndex; NumClosures;<br>
+      --idx, --NumClosures) {<br>
     CapturingScopeInfo *CSI = cast<CapturingScopeInfo>(FunctionScopes[idx]);<br>
     Expr *ThisExpr = 0;<br>
     QualType ThisTy = getCurrentThisType();<br>
@@ -801,6 +813,7 @@ void Sema::CheckCXXThisCapture(SourceLoc<br>
     bool isNested = NumClosures > 1;<br>
     CSI->addThisCapture(isNested, Loc, ThisTy, ThisExpr);<br>
   }<br>
+  return false;<br>
 }<br>
<br>
 ExprResult Sema::ActOnCXXThis(SourceLocation Loc) {<br>
@@ -5778,7 +5791,7 @@ ExprResult Sema::IgnoredValueConversions<br>
       if (Res.isInvalid())<br>
         return Owned(E);<br>
       E = Res.take();<br>
-    }<br>
+    }<br>
     return Owned(E);<br>
   }<br>
<br>
@@ -5802,6 +5815,123 @@ ExprResult Sema::IgnoredValueConversions<br>
   return Owned(E);<br>
 }<br>
<br>
+// If we can unambiguously determine whether Var can never be used<br>
+// in a constant expression, return true.<br>
+//  - if the variable and its initializer are non-dependent, then<br>
+//    we can unambiguously check if the variable is a constant expression.<br>
+//  - if the initializer is not value dependent - we can determine whether<br>
+//    it can be used to initialize a constant expression.  If Init can not<br>
+//    be used to initialize a constant expression we conclude that Var can<br>
+//    never be a constant expression.<br>
+//  - FXIME: if the initializer is dependent, we can still do some analysis and<br>
+//    identify certain cases unambiguously as non-const by using a Visitor:<br>
+//      - such as those that involve odr-use of a ParmVarDecl, involve a new<br>
+//        delete, lambda-expr, dynamic-cast, reinterpret-cast etc...<br>
+static inline bool VariableCanNeverBeAConstantExpression(VarDecl *Var,<br>
+    ASTContext &Context) {<br>
+  if (isa<ParmVarDecl>(Var)) return true;<br>
+  const VarDecl *DefVD = 0;<br>
+<br>
+  // If there is no initializer - this can not be a constant expression.<br>
+  if (!Var->getAnyInitializer(DefVD)) return true;<br>
+  assert(DefVD);<br>
+  if (DefVD->isWeak()) return false;<br>
+  EvaluatedStmt *Eval = DefVD->ensureEvaluatedStmt();<br>
+<br>
+  Expr *Init = cast<Expr>(Eval->Value);<br>
+<br>
+  if (Var->getType()->isDependentType() || Init->isValueDependent()) {<br>
+    if (!Init->isValueDependent())<br>
+      return !DefVD->checkInitIsICE();<br>
+    // FIXME: We might still be able to do some analysis of Init here<br>
+    // to conclude that even in a dependent setting, Init can never<br>
+    // be a constexpr - but for now admit agnosticity.<br>
+    return false;<br>
+  }<br>
+  return !IsVariableAConstantExpression(Var, Context);<br>
+}<br>
+<br>
+/// \brief Check if the current lambda scope has any potential captures, and<br>
+///  whether they can be captured by any of the enclosing lambdas that are<br>
+///  ready to capture. If there is a lambda that can capture a nested<br>
+///  potential-capture, go ahead and do so.  Also, check to see if any<br>
+///  variables are uncaptureable or do not involve an odr-use so do not<br>
+///  need to be captured.<br>
+<br>
+static void CheckLambdaCaptures(Expr *const FE,<br>
+    LambdaScopeInfo *const CurrentLSI, Sema &S) {<br>
+<br>
+  assert(!S.isUnevaluatedContext());<br>
+  assert(S.CurContext->isDependentContext());<br>
+  const bool IsFullExprInstantiationDependent =<br>
+      FE->isInstantiationDependent();<br>
+  // All the potentially captureable variables in the current nested<br>
+  // lambda (within a generic outer lambda), must be captured by an<br>
+  // outer lambda that is enclosed within a non-dependent context.<br>
+<br>
+  for (size_t I = 0, N = CurrentLSI->getNumPotentialVariableCaptures();<br>
+      I != N; ++I) {<br>
+    Expr *VarExpr = 0;<br>
+    VarDecl *Var = 0;<br>
+    CurrentLSI->getPotentialVariableCapture(I, Var, VarExpr);<br>
+    //<br>
+    if (CurrentLSI->isVariableExprMarkedAsNonODRUsed(VarExpr) &&<br>
+        !IsFullExprInstantiationDependent)<br>
+      continue;<br>
+    // Climb up until we find a lambda that can capture:<br>
+    //   - a generic-or-non-generic lambda call operator that is enclosed<br>
+    //     within a non-dependent context.<br>
+    unsigned FunctionScopeIndexOfCapturableLambda = 0;<br>
+    CXXMethodDecl *NearestCapturableCallOp = 0;<br>
+    if (NearestCapturableCallOp =<br>
+                          GetInnermostEnclosingCapturableLambda(<br>
+                                  S.FunctionScopes,<br>
+                                  FunctionScopeIndexOfCapturableLambda,<br>
+                                  S.CurContext, Var, S)) {<br>
+      MarkVarDeclODRUsed(Var, VarExpr->getExprLoc(),<br>
+          S, &FunctionScopeIndexOfCapturableLambda);<br>
+    }<br>
+    const bool IsVarNeverAConstantExpression =<br>
+        VariableCanNeverBeAConstantExpression(Var, S.Context);<br>
+    if (!IsFullExprInstantiationDependent || IsVarNeverAConstantExpression) {<br>
+      // This full expression is not instantiation dependent or the variable<br>
+      // can not be used in a constant expression - which means<br>
+      // this variable must be odr-used here, so diagnose a<br>
+      // capture violation early, if the variable is un-captureable.<br>
+      // This is purely for diagnosing errors early.  Otherwise, this<br>
+      // error would get diagnosed when the lambda becomes capture ready.<br>
+      QualType CaptureType, DeclRefType;<br>
+      SourceLocation ExprLoc = VarExpr->getExprLoc();<br>
+      if (S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,<br>
+                          /*EllipsisLoc*/ SourceLocation(),<br>
+                          /*BuildAndDiagnose*/false, CaptureType,<br>
+                          DeclRefType, 0)) {<br>
+        // We will never be able to capture this variable, and we need<br>
+        // to be able to in any and all instantiations, so diagnose it.<br>
+        S.tryCaptureVariable(Var, ExprLoc, S.TryCapture_Implicit,<br>
+                          /*EllipsisLoc*/ SourceLocation(),<br>
+                          /*BuildAndDiagnose*/true, CaptureType,<br>
+                          DeclRefType, 0);<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  if (CurrentLSI->hasPotentialThisCapture()) {<br>
+    unsigned FunctionScopeIndexOfCapturableLambda = 0;<br>
+    if (CXXMethodDecl *NearestCapturableCallOp =<br>
+                          GetInnermostEnclosingCapturableLambda(<br>
+                                  S.FunctionScopes,<br>
+                                  FunctionScopeIndexOfCapturableLambda,<br>
+                                  S.CurContext, /*0 is 'this'*/ 0, S)) {<br>
+      S.CheckCXXThisCapture(CurrentLSI->PotentialThisCaptureLocation,<br>
+          /*Explicit*/false, /*BuildAndDiagnose*/true,<br>
+          &FunctionScopeIndexOfCapturableLambda);<br>
+    }<br>
+  }<br>
+  CurrentLSI->clearPotentialCaptures();<br>
+}<br>
+<br>
+<br>
 ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,<br>
                                      bool DiscardedValue,<br>
                                      bool IsConstexpr) {<br>
@@ -5832,6 +5962,41 @@ ExprResult Sema::ActOnFinishFullExpr(Exp<br>
   }<br>
<br>
   CheckCompletedExpr(FullExpr.get(), CC, IsConstexpr);<br>
+<br>
+  // At the end of this full expression (which could be a deeply nested lambda),<br>
+  // if there is a potential capture within the nested lambda, have the outer<br>
+  // capture-able lambda try and capture it.<br>
+  // Consider the following code:<br>
+  // void f(int, int);<br>
+  // void f(const int&, double);<br>
+  // void foo() {<br>
+  //  const int x = 10, y = 20;<br>
+  //  auto L = [=](auto a) {<br>
+  //      auto M = [=](auto b) {<br>
+  //         f(x, b); <-- requires x to be captured by L and M<br>
+  //         f(y, a); <-- requires y to be captured by L, but not all Ms<br>
+  //      };<br>
+  //   };<br>
+  // }<br>
+<br>
+  // FIXME: Also consider what happens for something like this that involves<br>
+  // the gnu-extension statement-expressions or even lambda-init-captures:<br>
+  //   void f() {<br>
+  //     const int n = 0;<br>
+  //     auto L =  [&](auto a) {<br>
+  //       +n + ({ 0; a; });<br>
+  //     };<br>
+  //   }<br>
+  //<br>
+  //   Here, we see +n, and then the full-expression 0; ends, so we don't capture n<br>
+  //   (and instead remove it from our list of potential captures), and then the<br>
+  //   full-expression +n + ({ 0; }); ends, but it's too late for us to see that<br>
+  //   we need to capture n after all.<br>
+<br>
+  LambdaScopeInfo *const CurrentLSI = getCurLambda();<br>
+  if (CurrentLSI && CurrentLSI->hasPotentialCaptures() &&<br>
+      !FullExpr.isInvalid())<br>
+    CheckLambdaCaptures(FE, CurrentLSI, *this);<br>
   return MaybeCreateExprWithCleanups(FullExpr);<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaExprMember.cpp Wed Nov  6 23:17:06 2013<br>
@@ -11,6 +11,7 @@<br>
 //<br>
 //===----------------------------------------------------------------------===//<br>
 #include "clang/Sema/SemaInternal.h"<br>
+#include "clang/AST/ASTLambda.h"<br>
 #include "clang/AST/DeclCXX.h"<br>
 #include "clang/AST/DeclObjC.h"<br>
 #include "clang/AST/DeclTemplate.h"<br>
@@ -883,7 +884,54 @@ Sema::BuildMemberReferenceExpr(Expr *Bas<br>
     BaseType = BaseType->castAs<PointerType>()->getPointeeType();<br>
   }<br>
   R.setBaseObjectType(BaseType);<br>
-<br>
+<br>
+  LambdaScopeInfo *const CurLSI = getCurLambda();<br>
+  // If this is an implicit member reference and the overloaded<br>
+  // name refers to both static and non-static member functions<br>
+  // (i.e. BaseExpr is null) and if we are currently processing a lambda,<br>
+  // check if we should/can capture 'this'...<br>
+  // Keep this example in mind:<br>
+  //  struct X {<br>
+  //   void f(int) { }<br>
+  //   static void f(double) { }<br>
+  //<br>
+  //   int g() {<br>
+  //     auto L = [=](auto a) {<br>
+  //       return [](int i) {<br>
+  //         return [=](auto b) {<br>
+  //           f(b);<br>
+  //           //f(decltype(a){});<br>
+  //         };<br>
+  //       };<br>
+  //     };<br>
+  //     auto M = L(0.0);<br>
+  //     auto N = M(3);<br>
+  //     N(5.32); // OK, must not error.<br>
+  //     return 0;<br>
+  //   }<br>
+  //  };<br>
+  //<br>
+  if (!BaseExpr && CurLSI) {<br>
+    SourceLocation Loc = R.getNameLoc();<br>
+    if (SS.getRange().isValid())<br>
+      Loc = SS.getRange().getBegin();<br>
+    DeclContext *EnclosingFunctionCtx = CurContext->getParent()->getParent();<br>
+    // If the enclosing function is not dependent, then this lambda is<br>
+    // capture ready, so if we can capture this, do so.<br>
+    if (!EnclosingFunctionCtx->isDependentContext()) {<br>
+      // If the current lambda and all enclosing lambdas can capture 'this' -<br>
+      // then go ahead and capture 'this' (since our unresolved overload set<br>
+      // contains both static and non-static member functions).<br>
+      if (!CheckCXXThisCapture(Loc, /*Explcit*/false, /*Diagnose*/false))<br>
+        CheckCXXThisCapture(Loc);<br>
+    } else if (CurContext->isDependentContext()) {<br>
+      // ... since this is an implicit member reference, that might potentially<br>
+      // involve a 'this' capture, mark 'this' for potential capture in<br>
+      // enclosing lambdas.<br>
+      if (CurLSI->ImpCaptureStyle != CurLSI->ImpCap_None)<br>
+        CurLSI->addPotentialThisCapture(Loc);<br>
+    }<br>
+  }<br>
   const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo();<br>
   DeclarationName MemberName = MemberNameInfo.getName();<br>
   SourceLocation MemberLoc = MemberNameInfo.getLoc();<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed Nov  6 23:17:06 2013<br>
@@ -20,10 +20,117 @@<br>
 #include "clang/Sema/Scope.h"<br>
 #include "clang/Sema/ScopeInfo.h"<br>
 #include "clang/Sema/SemaInternal.h"<br>
+#include "clang/Sema/SemaLambda.h"<br>
 #include "TypeLocBuilder.h"<br>
 using namespace clang;<br>
 using namespace sema;<br>
<br>
+// returns -1 if none of the lambdas on the scope stack can capture.<br>
+// A lambda 'L' is capture-ready for a certain variable 'V' if,<br>
+//  - its enclosing context is non-dependent<br>
+//  - and if the chain of lambdas between L and the lambda in which<br>
+//    V is potentially used, call all capture or have captured V.<br>
+static inline int GetScopeIndexOfNearestCaptureReadyLambda(<br>
+    ArrayRef<clang::sema::FunctionScopeInfo*> FunctionScopes,<br>
+    DeclContext *const CurContext, VarDecl *VD) {<br>
+<br>
+  DeclContext *EnclosingDC = CurContext;<br>
+  // If VD is null, we are attempting to capture 'this'<br>
+  const bool IsCapturingThis = !VD;<br>
+  const bool IsCapturingVariable = !IsCapturingThis;<br>
+  int RetIndex = -1;<br>
+  unsigned CurScopeIndex = FunctionScopes.size() - 1;<br>
+  while (!EnclosingDC->isTranslationUnit() &&<br>
+      EnclosingDC->isDependentContext() && isLambdaCallOperator(EnclosingDC)) {<br>
+    RetIndex = CurScopeIndex;<br>
+    clang::sema::LambdaScopeInfo *LSI =<br>
+          cast<sema::LambdaScopeInfo>(FunctionScopes[CurScopeIndex]);<br>
+    // We have crawled up to an intervening lambda that contains the<br>
+    // variable declaration - so not only does it not need to capture;<br>
+    // none of the enclosing lambdas need to capture it, and since all<br>
+    // other nested lambdas are dependent (otherwise we wouldn't have<br>
+    // arrived here) - we don't yet have a lambda that can capture the<br>
+    // variable.<br>
+    if (IsCapturingVariable && VD->getDeclContext()->Equals(EnclosingDC))<br>
+      return -1;<br>
+    // All intervening lambda call operators have to be able to capture.<br>
+    // If they do not have a default implicit capture, check to see<br>
+    // if the entity has already been explicitly captured.<br>
+    // If even a single dependent enclosing lambda lacks the capability<br>
+    // to ever capture this variable, there is no further enclosing<br>
+    // non-dependent lambda that can capture this variable.<br>
+    if (LSI->ImpCaptureStyle == sema::LambdaScopeInfo::ImpCap_None) {<br>
+      if (IsCapturingVariable && !LSI->isCaptured(VD))<br>
+        return -1;<br>
+      if (IsCapturingThis && !LSI->isCXXThisCaptured())<br>
+        return -1;<br>
+    }<br>
+    EnclosingDC = getLambdaAwareParentOfDeclContext(EnclosingDC);<br>
+    --CurScopeIndex;<br>
+  }<br>
+  // If the enclosingDC is not dependent, then the immediately nested lambda<br>
+  // is capture-ready.<br>
+  if (!EnclosingDC->isDependentContext())<br>
+    return RetIndex;<br>
+  return -1;<br>
+}<br>
+// Given a lambda's call operator and a variable (or null for 'this'),<br>
+// compute the nearest enclosing lambda that is capture-ready (i.e<br>
+// the enclosing context is not dependent, and all intervening lambdas can<br>
+// either implicitly or explicitly capture Var)<br>
+//<br>
+// The approach is as follows, for the entity VD ('this' if null):<br>
+//   - start with the current lambda<br>
+//     - if it is non-dependent and can capture VD, return it.<br>
+//     - if it is dependent and has an implicit or explicit capture, check its parent<br>
+//       whether the parent is non-depdendent and all its intervening lambdas<br>
+//       can capture, if so return the child.<br>
+//       [Note: When we hit a generic lambda specialization, do not climb up<br>
+//         the scope stack any further since not only do we not need to,<br>
+//         the scope stack will often not be synchronized with any lambdas<br>
+//         enclosing the specialized generic lambda]<br>
+//<br>
+// Return the CallOperator of the capturable lambda and set function scope<br>
+// index to the correct index within the function scope stack to correspond<br>
+// to the capturable lambda.<br>
+// If VarDecl *VD is null, we check for 'this' capture.<br>
+CXXMethodDecl* clang::GetInnermostEnclosingCapturableLambda(<br>
+                             ArrayRef<sema::FunctionScopeInfo*> FunctionScopes,<br>
+                             unsigned &FunctionScopeIndex,<br>
+                             DeclContext *const CurContext, VarDecl *VD,<br>
+                             Sema &S) {<br>
+<br>
+  const int IndexOfCaptureReadyLambda =<br>
+      GetScopeIndexOfNearestCaptureReadyLambda(FunctionScopes,CurContext, VD);<br>
+  if (IndexOfCaptureReadyLambda == -1) return 0;<br>
+  assert(IndexOfCaptureReadyLambda >= 0);<br>
+  const unsigned IndexOfCaptureReadyLambdaU =<br>
+      static_cast<unsigned>(IndexOfCaptureReadyLambda);<br>
+  sema::LambdaScopeInfo *const CaptureReadyLambdaLSI =<br>
+      cast<sema::LambdaScopeInfo>(FunctionScopes[IndexOfCaptureReadyLambdaU]);<br>
+  // If VD is null, we are attempting to capture 'this'<br>
+  const bool IsCapturingThis = !VD;<br>
+  const bool IsCapturingVariable = !IsCapturingThis;<br>
+<br>
+  if (IsCapturingVariable) {<br>
+    // Now check to see if this lambda can truly capture, and also<br>
+    // if all enclosing lambdas of this lambda allow this capture.<br>
+    QualType CaptureType, DeclRefType;<br>
+    const bool CanCaptureVariable = !S.tryCaptureVariable(VD,<br>
+      /*ExprVarIsUsedInLoc*/SourceLocation(), clang::Sema::TryCapture_Implicit,<br>
+      /*EllipsisLoc*/ SourceLocation(),<br>
+      /*BuildAndDiagnose*/false, CaptureType, DeclRefType,<br>
+      &IndexOfCaptureReadyLambdaU);<br>
+    if (!CanCaptureVariable) return 0;<br>
+  } else {<br>
+    const bool CanCaptureThis = !S.CheckCXXThisCapture(<br>
+        CaptureReadyLambdaLSI->PotentialThisCaptureLocation, false, false,<br>
+        &IndexOfCaptureReadyLambdaU);<br>
+    if (!CanCaptureThis) return 0;<br>
+  } // end 'this' capture test<br>
+  FunctionScopeIndex = IndexOfCaptureReadyLambdaU;<br>
+  return CaptureReadyLambdaLSI->CallOperator;<br>
+}<br>
<br>
 static inline TemplateParameterList *<br>
 getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {<br>
@@ -1258,15 +1365,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceL<br>
       break;<br>
     }<br>
   }<br>
-  // TODO: Implement capturing.<br>
-  if (Lambda->isGenericLambda()) {<br>
-    if (!Captures.empty() || Lambda->getCaptureDefault() != LCD_None) {<br>
-      Diag(Lambda->getIntroducerRange().getBegin(),<br>
-        diag::err_glambda_not_fully_implemented)<br>
-        << " capturing not implemented yet";<br>
-      return ExprError();<br>
-    }<br>
-  }<br>
+<br>
   return MaybeBindToTemporary(Lambda);<br>
 }<br>
<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp Wed Nov  6 23:17:06 2013<br>
@@ -1,24 +1,24 @@<br>
 // RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify<br>
-<br>
+//expected-no-diagnostics<br>
 namespace lambda_capturing {<br>
 // FIXME: Once return type deduction is implemented for generic lambdas<br>
 // this will need to be updated.<br>
 void test() {<br>
   int i = 10;<br>
   {<br>
-    auto L = [=](auto a) -> int { //expected-error{{unimplemented}}<br>
+    auto L = [=](auto a) -> int {<br>
       return i + a;<br>
     };<br>
     L(3);<br>
   }<br>
   {<br>
-    auto L = [i](auto a) -> int { //expected-error{{unimplemented}}<br>
+    auto L = [i](auto a) -> int {<br>
       return i + a;<br>
     };<br>
     L(3);<br>
   }<br>
   {<br>
-    auto L = [i = i](auto a) -> int { //expected-error{{unimplemented}}<br>
+    auto L = [i=i](auto a) -> int {<br>
       return i + a;<br>
     };<br>
     L(3);<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp Wed Nov  6 23:17:06 2013<br>
@@ -14,10 +14,12 @@ struct P {<br>
   virtual ~P();<br>
 };<br>
<br>
-void unevaluated_operand(P &p, int i) {<br>
+void unevaluated_operand(P &p, int i) { //expected-note{{declared here}}<br>
   // FIXME: this should only emit one error.<br>
   int i2 = sizeof([](auto a, auto b)->void{}(3, '4')); // expected-error{{lambda expression in an unevaluated operand}} \<br>
                                                        // expected-error{{invalid application of 'sizeof'}}<br>
   const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p; return p; }(i));<br>
-  const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i));  // expected-error{{lambda expression in an unevaluated operand}}<br>
+  const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i));  // expected-error{{lambda expression in an unevaluated operand}}\<br>
+                                                                         // expected-error{{cannot be implicitly captured}}\<br>
+                                                                         // expected-note{{begins here}}<br>
 }<br>
<br>
Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp (original)<br>
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp Wed Nov  6 23:17:06 2013<br>
@@ -112,7 +112,7 @@ void test2() {<br>
 namespace nested_lambdas {<br>
   int test() {<br>
     auto L = [](auto a) {<br>
-                 return [=](auto b) {  //expected-error{{unimplemented}}<br>
+                 return [=](auto b) {<br>
                            return a + b;<br>
                         };<br>
               };<br>
<br>
Added: cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp?rev=194188&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp?rev=194188&view=auto</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp (added)<br>
+++ cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas-capturing.cpp Wed Nov  6 23:17:06 2013<br>
@@ -0,0 +1,1363 @@<br>
+// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm-only %s<br>
+// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING<br>
+// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS<br>
+// DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING<br>
+<br>
+constexpr int ODRUSE_SZ = sizeof(char);<br>
+<br>
+template<class T, int N><br>
+void f(T, const int (&)[N]) { }<br>
+<br>
+template<class T><br>
+void f(const T&, const int (&)[ODRUSE_SZ]) { }<br>
+<br>
+#define DEFINE_SELECTOR(x)   \<br>
+  int selector_ ## x[sizeof(x) == ODRUSE_SZ ? ODRUSE_SZ : ODRUSE_SZ + 5]<br>
+<br>
+#define F_CALL(x, a) f(x, selector_ ## a)<br>
+<br>
+// This is a risky assumption, because if an empty class gets captured by value<br>
+// the lambda's size will still be '1'<br>
+#define ASSERT_NO_CAPTURES(L) static_assert(sizeof(L) == 1, "size of closure with no captures must be 1")<br>
+#define ASSERT_CLOSURE_SIZE_EXACT(L, N) static_assert(sizeof(L) == (N), "size of closure must be " #N)<br>
+#define ASSERT_CLOSURE_SIZE(L, N) static_assert(sizeof(L) >= (N), "size of closure must be >=" #N)<br>
+<br>
+<br>
+namespace sample {<br>
+  struct X {<br>
+    int i;<br>
+    X(int i) : i(i) { }<br>
+  };<br>
+}<br>
+<br>
+namespace test_transformations_in_templates {<br>
+template<class T> void foo(T t) {<br>
+  auto L = [](auto a) { return a; };<br>
+}<br>
+template<class T> void foo2(T t) {<br>
+  auto L = [](auto a) -> void {<br>
+    auto M = [](char b) -> void {<br>
+      auto N = [](auto c) -> void {<br>
+        int selector[sizeof(c) == 1 ?<br>
+                      (sizeof(b) == 1 ? 1 : 2)<br>
+                      : 2<br>
+                    ]{};<br>
+      };<br>
+      N('a');<br>
+    };<br>
+  };<br>
+  L(3.14);<br>
+}<br>
+<br>
+void doit() {<br>
+  foo(3);<br>
+  foo('a');<br>
+  foo2('A');<br>
+}<br>
+}<br>
+<br>
+namespace test_return_type_deduction {<br>
+<br>
+void doit() {<br>
+<br>
+  auto L = [](auto a, auto b) {<br>
+    if ( a > b ) return a;<br>
+    return b;<br>
+  };<br>
+  L(2, 4);<br>
+  {<br>
+    auto L2 = [](auto a, int i) {<br>
+      return a + i;<br>
+    };<br>
+    L2(3.14, 2);<br>
+  }<br>
+  {<br>
+    int a; //expected-note{{declared here}}<br>
+    auto B = []() { return ^{ return a; }; }; //expected-error{{cannot be implicitly capture}}\<br>
+                                              //expected-note{{begins here}}<br>
+  //[](){ return ({int b = 5; return 'c'; 'x';}); };<br>
+<br>
+  //auto X = ^{ return a; };<br>
+<br>
+  //auto Y = []() -> auto { return 3; return 'c'; };<br>
+<br>
+  }<br>
+}<br>
+}<br>
+<br>
+<br>
+namespace test_no_capture{<br>
+void doit() {<br>
+  const int x = 10; //expected-note{{declared here}}<br>
+  {<br>
+    // should not capture 'x' - variable undergoes lvalue-to-rvalue<br>
+    auto L = [=](auto a) {<br>
+      int y = x;<br>
+      return a + y;<br>
+    };<br>
+    ASSERT_NO_CAPTURES(L);<br>
+  }<br>
+  {<br>
+    // should not capture 'x' - even though certain instantiations require<br>
+    auto L = [](auto a) { //expected-note{{begins here}}<br>
+      DEFINE_SELECTOR(a);<br>
+      F_CALL(x, a); //expected-error{{'x' cannot be implicitly captured}}<br>
+    };<br>
+    ASSERT_NO_CAPTURES(L);<br>
+    L('s'); //expected-note{{in instantiation of}}<br>
+  }<br>
+  {<br>
+    // Does not capture because no default capture in inner most lambda 'b'<br>
+    auto L = [=](auto a) {<br>
+      return [=](int p) {<br>
+        return [](auto b) {<br>
+          DEFINE_SELECTOR(a);<br>
+          F_CALL(x, a);<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    ASSERT_NO_CAPTURES(L);<br>
+  }<br>
+}  // doit<br>
+} // namespace<br>
+<br>
+namespace test_capture_of_potentially_evaluated_expression {<br>
+void doit() {<br>
+  const int x = 5;<br>
+  {<br>
+    auto L = [=](auto a) {<br>
+      DEFINE_SELECTOR(a);<br>
+      F_CALL(x, a);<br>
+    };<br>
+    static_assert(sizeof(L) == 4, "Must be captured");<br>
+  }<br>
+  {<br>
+    int j = 0; //expected-note{{declared}}<br>
+    auto L = [](auto a) {  //expected-note{{begins here}}<br>
+      return j + 1; //expected-error{{cannot be implicitly captured}}<br>
+    };<br>
+  }<br>
+  {<br>
+    const int x = 10;<br>
+    auto L = [](auto a) {<br>
+      //const int y = 20;<br>
+      return [](int p) {<br>
+        return [](auto b) {<br>
+          DEFINE_SELECTOR(a);<br>
+          F_CALL(x, a);<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(3);<br>
+    auto N = M(5);<br>
+<br>
+  }<br>
+<br>
+  { // if the nested capture does not implicitly or explicitly allow any captures<br>
+    // nothing should capture - and instantiations will create errors if needed.<br>
+    const int x = 0;<br>
+    auto L = [=](auto a) { // <-- #A<br>
+      const int y = 0;<br>
+      return [](auto b) { // <-- #B<br>
+        int c[sizeof(b)];<br>
+        f(x, c);<br>
+        f(y, c);<br>
+        int i = x;<br>
+      };<br>
+    };<br>
+    ASSERT_NO_CAPTURES(L);<br>
+    auto M_int = L(2);<br>
+    ASSERT_NO_CAPTURES(M_int);<br>
+  }<br>
+  { // Permutations of this example must be thoroughly tested!<br>
+    const int x = 0;<br>
+    sample::X cx{5};<br>
+    auto L = [=](auto a) {<br>
+      const int z = 3;<br>
+      return [&,a](auto b) {<br>
+        const int y = 5;<br>
+        return [=](auto c) {<br>
+          int d[sizeof(a) == sizeof(c) || sizeof(c) == sizeof(b) ? 2 : 1];<br>
+          f(x, d);<br>
+          f(y, d);<br>
+          f(z, d);<br>
+          decltype(a) A = a;<br>
+          decltype(b) B = b;<br>
+          const int &i = cx.i;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(3)(3.5);<br>
+    M(3.14);<br>
+  }<br>
+}<br>
+namespace Test_no_capture_of_clearly_no_odr_use {<br>
+auto foo() {<br>
+ const int x = 10;<br>
+ auto L = [=](auto a) {<br>
+    return  [=](auto b) {<br>
+      return [=](auto c) {<br>
+        int A = x;<br>
+        return A;<br>
+      };<br>
+    };<br>
+  };<br>
+  auto M = L(1);<br>
+  auto N = M(2.14);<br>
+  ASSERT_NO_CAPTURES(L);<br>
+  ASSERT_NO_CAPTURES(N);<br>
+<br>
+  return 0;<br>
+}<br>
+}<br>
+<br>
+namespace Test_capture_of_odr_use_var {<br>
+auto foo() {<br>
+ const int x = 10;<br>
+ auto L = [=](auto a) {<br>
+    return  [=](auto b) {<br>
+      return [=](auto c) {<br>
+        int A = x;<br>
+        const int &i = x;<br>
+        decltype(a) A2 = a;<br>
+        return A;<br>
+      };<br>
+    };<br>
+  };<br>
+  auto M_int = L(1);<br>
+  auto N_int_int = M_int(2);<br>
+  ASSERT_CLOSURE_SIZE_EXACT(L, sizeof(x));<br>
+  // M_int captures both a & x<br>
+  ASSERT_CLOSURE_SIZE_EXACT(M_int, sizeof(x) + sizeof(int));<br>
+  // N_int_int captures both a & x<br>
+  ASSERT_CLOSURE_SIZE_EXACT(N_int_int, sizeof(x) + sizeof(int));<br>
+  auto M_double = L(3.14);<br>
+  ASSERT_CLOSURE_SIZE(M_double, sizeof(x) + sizeof(double));<br>
+<br>
+  return 0;<br>
+}<br>
+auto run = foo();<br>
+}<br>
+<br>
+}<br>
+namespace more_nested_captures_1 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double, ...) { }<br>
+  template<class R><br>
+  static void f(const int&, R, ...) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10; //expected-note{{declared here}}<br>
+    auto L = [](auto a) {<br>
+       return [=](auto b) {<br>
+        return [=](auto c) {<br>
+          f(x, c, b, a);  //expected-error{{reference to local variable 'x'}}<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N = M('b');<br>
+    N(3.14);<br>
+    N(5);  //expected-note{{in instantiation of}}<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}}<br>
+}<br>
+<br>
+<br>
+namespace more_nested_captures_1_1 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double, ...) { }<br>
+  template<class R><br>
+  static void f(const int&, R, ...) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10; //expected-note{{declared here}}<br>
+    auto L = [](auto a) {<br>
+       return [=](char b) {<br>
+        return [=](auto c) {<br>
+          f(x, c, b, a);  //expected-error{{reference to local variable 'x'}}<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N = M('b');<br>
+    N(3.14);<br>
+    N(5);  //expected-note{{in instantiation of}}<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}}<br>
+}<br>
+namespace more_nested_captures_1_2 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double, ...) { }<br>
+  template<class R><br>
+  static void f(const int&, R, ...) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10;<br>
+    auto L = [=](auto a) {<br>
+       return [=](char b) {<br>
+        return [=](auto c) {<br>
+          f(x, c, b, a);<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N = M('b');<br>
+    N(3.14);<br>
+    N(5);<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo(3.14), 0);<br>
+}<br>
+<br>
+namespace more_nested_captures_1_3 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double, ...) { }<br>
+  template<class R><br>
+  static void f(const int&, R, ...) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10; //expected-note{{declared here}}<br>
+    auto L = [=](auto a) {<br>
+       return [](auto b) {<br>
+        const int y = 0;<br>
+        return [=](auto c) {<br>
+          f(x, c, b);  //expected-error{{reference to local variable 'x'}}<br>
+          f(y, b, c);<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N = M('b');<br>
+    N(3.14);<br>
+    N(5);  //expected-note{{in instantiation of}}<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}}<br>
+}<br>
+<br>
+<br>
+namespace more_nested_captures_1_4 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double, ...) { }<br>
+  template<class R><br>
+  static void f(const int&, R, ...) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10; //expected-note{{declared here}}<br>
+    auto L = [=](auto a) {<br>
+       T t2{t};<br>
+       return [](auto b) {<br>
+        const int y = 0; //expected-note{{declared here}}<br>
+        return [](auto c) { //expected-note 2{{lambda expression begins here}}<br>
+          f(x, c);  //expected-error{{variable 'x'}}<br>
+          f(y, c);  //expected-error{{variable 'y'}}<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N_char = M('b');<br>
+    N_char(3.14);<br>
+    auto N_double = M(3.14);<br>
+    N_double(3.14);<br>
+    N_char(3);  //expected-note{{in instantiation of}}<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo('a'), 0); //expected-note{{in instantiation of}}<br>
+}<br>
+<br>
+<br>
+namespace more_nested_captures_2 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double) { }<br>
+  template<class R><br>
+  static void f(const int&, R) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10;<br>
+    auto L = [=](auto a) {<br>
+       return [=](auto b) {<br>
+        return [=](auto c) {<br>
+          f(x, c);<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N = M('b');<br>
+    N(3);<br>
+    N(3.14);<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo(3.14), 0);<br>
+<br>
+}<br>
+<br>
+namespace more_nested_captures_3 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double) { }<br>
+  template<class R><br>
+  static void f(const int&, R) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10; //expected-note{{declared here}}<br>
+    auto L = [](auto a) {<br>
+       return [=](auto b) {<br>
+        return [=](auto c) {<br>
+          f(x, c);   //expected-error{{reference to local variable 'x'}}<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N = M('b');<br>
+    N(3); //expected-note{{in instantiation of}}<br>
+    N(3.14);<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}}<br>
+<br>
+}<br>
+<br>
+namespace more_nested_captures_4 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double) { }<br>
+  template<class R><br>
+  static void f(const int&, R) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10;  //expected-note{{'x' declared here}}<br>
+    auto L = [](auto a) {<br>
+       return [=](char b) {<br>
+        return [=](auto c) {<br>
+          f(x, c);  //expected-error{{reference to local variable 'x'}}<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N = M('b');<br>
+    N(3); //expected-note{{in instantiation of}}<br>
+    N(3.14);<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo(3.14), 0); //expected-note{{in instantiation of}}<br>
+<br>
+}<br>
+<br>
+namespace more_nested_captures_5 {<br>
+template<class T> struct Y {<br>
+  static void f(int, double) { }<br>
+  template<class R><br>
+  static void f(const int&, R) { }<br>
+  template<class R><br>
+  void foo(R t) {<br>
+    const int x = 10;<br>
+    auto L = [=](auto a) {<br>
+       return [=](char b) {<br>
+        return [=](auto c) {<br>
+          f(x, c);<br>
+          return 0;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(t);<br>
+    auto N = M('b');<br>
+    N(3);<br>
+    N(3.14);<br>
+  }<br>
+};<br>
+Y<int> yi;<br>
+int run = (yi.foo(3.14), 0);<br>
+<br>
+}<br>
+<br>
+namespace lambdas_in_NSDMIs {<br>
+template<class T><br>
+  struct L {<br>
+      T t{};<br>
+      T t2 = ([](auto a) { return [](auto b) { return b; };})(t)(t);<br>
+      T t3 = ([](auto a) { return a; })(t);<br>
+  };<br>
+  L<int> l;<br>
+  int run = l.t2;<br>
+}<br>
+namespace test_nested_decltypes_in_trailing_return_types {<br>
+int foo() {<br>
+  auto L = [](auto a) {<br>
+      return [](auto b, decltype(a) b2) -> decltype(a) {<br>
+        return decltype(a){};<br>
+      };<br>
+  };<br>
+  auto M = L(3.14);<br>
+  M('a', 6.26);<br>
+  return 0;<br>
+}<br>
+}<br>
+<br>
+namespace more_this_capture_1 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+  void foo() {<br>
+    {<br>
+      auto L = [=](auto a) {<br>
+        f(a);<br>
+      };<br>
+      L(3);<br>
+      L(3.13);<br>
+    }<br>
+    {<br>
+      auto L = [](auto a) {<br>
+        f(a); //expected-error{{this}}<br>
+      };<br>
+      L(3.13);<br>
+      L(2); //expected-note{{in instantiation}}<br>
+    }<br>
+  }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [](int i) {<br>
+        return [=](auto b) {<br>
+          f(b);<br>
+          int x = i;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0.0);<br>
+    auto N = M(3);<br>
+    N(5.32); // OK<br>
+    return 0;<br>
+  }<br>
+};<br>
+int run = X{}.g();<br>
+}<br>
+namespace more_this_capture_1_1 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [](int i) {<br>
+        return [=](auto b) {<br>
+          f(decltype(a){}); //expected-error{{this}}<br>
+          int x = i;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0.0);<br>
+    auto N = M(3);<br>
+    N(5.32); // OK<br>
+    L(3); // expected-note{{instantiation}}<br>
+    return 0;<br>
+  }<br>
+};<br>
+int run = X{}.g();<br>
+}<br>
+<br>
+namespace more_this_capture_1_1_1 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [](auto b) {<br>
+        return [=](int i) {<br>
+          f(b);<br>
+          f(decltype(a){}); //expected-error{{this}}<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0.0);  // OK<br>
+    auto N = M(3.3); //OK<br>
+    auto M_int = L(0); //expected-note{{instantiation}}<br>
+    return 0;<br>
+  }<br>
+};<br>
+int run = X{}.g();<br>
+}<br>
+<br>
+<br>
+namespace more_this_capture_1_1_1_1 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [](auto b) {<br>
+        return [=](int i) {<br>
+          f(b); //expected-error{{this}}<br>
+          f(decltype(a){});<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M_double = L(0.0);  // OK<br>
+    auto N = M_double(3); //expected-note{{instantiation}}<br>
+<br>
+    return 0;<br>
+  }<br>
+};<br>
+int run = X{}.g();<br>
+}<br>
+<br>
+namespace more_this_capture_2 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [](int i) {<br>
+        return [=](auto b) {<br>
+          f(b); //expected-error{{'this' cannot}}<br>
+          int x = i;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0.0);<br>
+    auto N = M(3);<br>
+    N(5); // NOT OK expected-note{{in instantiation of}}<br>
+    return 0;<br>
+  }<br>
+};<br>
+int run = X{}.g();<br>
+}<br>
+namespace diagnose_errors_early_in_generic_lambdas {<br>
+<br>
+int foo()<br>
+{<br>
+<br>
+  { // This variable is used and must be caught early, do not need instantiation<br>
+    const int x = 0; //expected-note{{declared}}<br>
+    auto L = [](auto a) { //expected-note{{begins}}<br>
+      const int &r = x; //expected-error{{variable}}<br>
+    };<br>
+  }<br>
+  { // This variable is not used<br>
+    const int x = 0;<br>
+    auto L = [](auto a) {<br>
+      int i = x;<br>
+    };<br>
+  }<br>
+  {<br>
+<br>
+    const int x = 0; //expected-note{{declared}}<br>
+    auto L = [=](auto a) { // <-- #A<br>
+      const int y = 0;<br>
+      return [](auto b) { //expected-note{{begins}}<br>
+        int c[sizeof(b)];<br>
+        f(x, c);<br>
+        f(y, c);<br>
+        int i = x;<br>
+        // This use will always be an error regardless of instantatiation<br>
+        // so diagnose this early.<br>
+        const int &r = x; //expected-error{{variable}}<br>
+      };<br>
+    };<br>
+<br>
+  }<br>
+  return 0;<br>
+}<br>
+<br>
+int run = foo();<br>
+}<br>
+<br>
+namespace generic_nongenerics_interleaved_1 {<br>
+int foo() {<br>
+  {<br>
+    auto L = [](int a) {<br>
+      int y = 10;<br>
+      return [=](auto b) {<br>
+        return a + y;<br>
+      };<br>
+    };<br>
+    auto M = L(3);<br>
+    M(5);<br>
+  }<br>
+  {<br>
+    int x;<br>
+    auto L = [](int a) {<br>
+      int y = 10;<br>
+      return [=](auto b) {<br>
+        return a + y;<br>
+      };<br>
+    };<br>
+    auto M = L(3);<br>
+    M(5);<br>
+  }<br>
+  {<br>
+    // FIXME: why are there 2 error messages here?<br>
+    int x;<br>
+    auto L = [](auto a) { //expected-note {{declared here}}<br>
+      int y = 10; //expected-note {{declared here}}<br>
+      return [](int b) { //expected-note 2{{expression begins here}}<br>
+        return [=] (auto c) {<br>
+          return a + y; //expected-error 2{{cannot be implicitly captured}}<br>
+        };<br>
+      };<br>
+    };<br>
+  }<br>
+  {<br>
+    int x;<br>
+    auto L = [](auto a) {<br>
+      int y = 10;<br>
+      return [=](int b) {<br>
+        return [=] (auto c) {<br>
+          return a + y;<br>
+        };<br>
+      };<br>
+    };<br>
+  }<br>
+  return 1;<br>
+}<br>
+<br>
+int run = foo();<br>
+}<br>
+namespace dont_capture_refs_if_initialized_with_constant_expressions {<br>
+<br>
+auto foo(int i) {<br>
+  // This is surprisingly not odr-used within the lambda!<br>
+  static int j;<br>
+  j = i;<br>
+  int &ref_j = j;<br>
+  return [](auto a) { return ref_j; }; // ok<br>
+}<br>
+<br>
+template<class T><br>
+auto foo2(T t) {<br>
+  // This is surprisingly not odr-used within the lambda!<br>
+  static T j;<br>
+  j = t;<br>
+  T &ref_j = j;<br>
+  return [](auto a) { return ref_j; }; // ok<br>
+}<br>
+<br>
+int do_test() {<br>
+  auto L = foo(3);<br>
+  auto L_int = L(3);<br>
+  auto L_char = L('a');<br>
+  auto L1 = foo2(3.14);<br>
+  auto L1_int = L1(3);<br>
+  auto L1_char = L1('a');<br>
+  return 0;<br>
+}<br>
+<br>
+} // dont_capture_refs_if_initialized_with_constant_expressions<br>
+<br>
+namespace test_conversion_to_fptr {<br>
+<br>
+template<class T> struct X {<br>
+<br>
+  T (*fp)(T) = [](auto a) { return a; };<br>
+<br>
+};<br>
+<br>
+X<int> xi;<br>
+<br>
+template<class T><br>
+void fooT(T t, T (*fp)(T) = [](auto a) { return a; }) {<br>
+  fp(t);<br>
+}<br>
+<br>
+int test() {<br>
+{<br>
+  auto L = [](auto a) { return a; };<br>
+  int (*fp)(int) = L;<br>
+  fp(5);<br>
+  L(3);<br>
+  char (*fc)(char) = L;<br>
+  fc('b');<br>
+  L('c');<br>
+  double (*fd)(double) = L;<br>
+  fd(3.14);<br>
+  fd(6.26);<br>
+  L(4.25);<br>
+}<br>
+{<br>
+  auto L = [](auto a) ->int { return a; }; //expected-note 2{{candidate template ignored}}<br>
+  int (*fp)(int) = L;<br>
+  char (*fc)(char) = L; //expected-error{{no viable conversion}}<br>
+  double (*fd)(double) = L; //expected-error{{no viable conversion}}<br>
+}<br>
+{<br>
+  int x = 5;<br>
+  auto L = [=](auto b, char c = 'x') {<br>
+    int i = x;<br>
+    return [](auto a) ->decltype(a) { return a; };<br>
+  };<br>
+  int (*fp)(int) = L(8);<br>
+  fp(5);<br>
+  L(3);<br>
+  char (*fc)(char) = L('a');<br>
+  fc('b');<br>
+  L('c');<br>
+  double (*fd)(double) = L(3.14);<br>
+  fd(3.14);<br>
+  fd(6.26);<br>
+<br>
+}<br>
+{<br>
+ auto L = [=](auto b) {<br>
+    return [](auto a) ->decltype(b)* { return (decltype(b)*)0; };<br>
+  };<br>
+  int* (*fp)(int) = L(8);<br>
+  fp(5);<br>
+  L(3);<br>
+  char* (*fc)(char) = L('a');<br>
+  fc('b');<br>
+  L('c');<br>
+  double* (*fd)(double) = L(3.14);<br>
+  fd(3.14);<br>
+  fd(6.26);<br>
+}<br>
+{<br>
+ auto L = [=](auto b) {<br>
+    return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; //expected-note{{candidate template ignored}}<br>
+  };<br>
+  char* (*fp)(int) = L('8');<br>
+  fp(5);<br>
+  char* (*fc)(char) = L('a');<br>
+  fc('b');<br>
+  double* (*fi)(int) = L(3.14);<br>
+  fi(5);<br>
+  int* (*fi2)(int) = L(3.14); //expected-error{{no viable conversion}}<br>
+}<br>
+<br>
+{<br>
+ auto L = [=](auto b) {<br>
+    return [](auto a) {<br>
+      return [=](auto c) {<br>
+        return [](auto d) ->decltype(a + b + c + d) { return d; };<br>
+      };<br>
+    };<br>
+  };<br>
+  int (*fp)(int) = L('8')(3)(short{});<br>
+  double (*fs)(char) = L(3.14)(short{})('4');<br>
+}<br>
+<br>
+  fooT(3);<br>
+  fooT('a');<br>
+  fooT(3.14);<br>
+  fooT("abcdefg");<br>
+  return 0;<br>
+}<br>
+int run2 = test();<br>
+<br>
+}<br>
+<br>
+<br>
+namespace this_capture {<br>
+void f(char, int) { }<br>
+template<class T><br>
+void f(T, const int&) { }<br>
+<br>
+struct X {<br>
+  int x = 0;<br>
+  void foo() {<br>
+    auto L = [=](auto a) {<br>
+         return [=](auto b) {<br>
+            //f(a, x++);<br>
+            x++;<br>
+         };<br>
+    };<br>
+    L('a')(5);<br>
+    L('b')(4);<br>
+    L(3.14)('3');<br>
+<br>
+  }<br>
+<br>
+};<br>
+<br>
+int run = (X{}.foo(), 0);<br>
+<br>
+namespace this_capture_unresolvable {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto lam = [=](auto a) { f(a); }; // captures 'this'<br>
+    lam(0); // ok.<br>
+    lam(0.0); // ok.<br>
+    return 0;<br>
+  }<br>
+  int g2() {<br>
+    auto lam = [](auto a) { f(a); }; // expected-error{{'this'}}<br>
+    lam(0); // expected-note{{in instantiation of}}<br>
+    lam(0.0); // ok.<br>
+    return 0;<br>
+  }<br>
+  double (*fd)(double) = [](auto a) { f(a); return a; };<br>
+<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+<br>
+}<br>
+<br>
+namespace check_nsdmi_and_this_capture_of_member_functions {<br>
+<br>
+struct FunctorDouble {<br>
+  template<class T> FunctorDouble(T t) { t(2.14); };<br>
+};<br>
+struct FunctorInt {<br>
+  template<class T> FunctorInt(T t) { t(2); }; //expected-note{{in instantiation of}}<br>
+};<br>
+<br>
+template<class T> struct YUnresolvable {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  T t = [](auto a) { f(a); return a; };<br>
+  T t2 = [=](auto b) { f(b); return b; };<br>
+};<br>
+<br>
+template<class T> struct YUnresolvable2 {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}} \<br>
+                                        //expected-note{{in instantiation of}}<br>
+  T t2 = [=](auto b) { f(b); return b; };<br>
+};<br>
+<br>
+<br>
+YUnresolvable<FunctorDouble> yud;<br>
+// This will cause an error since it call's with an int and calls a member function.<br>
+YUnresolvable2<FunctorInt> yui;<br>
+<br>
+<br>
+template<class T> struct YOnlyStatic {<br>
+  static void f(double) { }<br>
+<br>
+  T t = [](auto a) { f(a); return a; };<br>
+};<br>
+YOnlyStatic<FunctorDouble> yos;<br>
+template<class T> struct YOnlyNonStatic {<br>
+  void f(int) { }<br>
+<br>
+  T t = [](auto a) { f(a); return a; }; //expected-error{{'this'}}<br>
+};<br>
+<br>
+<br>
+}<br>
+<br>
+<br>
+namespace check_nsdmi_and_this_capture_of_data_members {<br>
+<br>
+struct FunctorDouble {<br>
+  template<class T> FunctorDouble(T t) { t(2.14); };<br>
+};<br>
+struct FunctorInt {<br>
+  template<class T> FunctorInt(T t) { t(2); };<br>
+};<br>
+<br>
+template<class T> struct YThisCapture {<br>
+  const int x = 10;<br>
+  static double d;<br>
+  T t = [](auto a) { return x; }; //expected-error{{'this'}}<br>
+  T t2 = [](auto b) {  return d; };<br>
+  T t3 = [this](auto a) {<br>
+          return [=](auto b) {<br>
+            return x;<br>
+         };<br>
+  };<br>
+  T t4 = [=](auto a) {<br>
+          return [=](auto b) {<br>
+            return x;<br>
+         };<br>
+  };<br>
+  T t5 = [](auto a) {<br>
+          return [=](auto b) {<br>
+            return x;  //expected-error{{'this'}}<br>
+         };<br>
+  };<br>
+};<br>
+<br>
+template<class T> double YThisCapture<T>::d = 3.14;<br>
+<br>
+<br>
+}<br>
+<br>
+<br>
+#ifdef DELAYED_TEMPLATE_PARSING<br>
+template<class T> void foo_no_error(T t) {<br>
+  auto L = []()<br>
+    { return t; };<br>
+}<br>
+template<class T> void foo(T t) { //expected-note 2{{declared here}}<br>
+  auto L = []()  //expected-note 2{{begins here}}<br>
+    { return t; }; //expected-error 2{{cannot be implicitly captured}}<br>
+}<br>
+template void foo(int); //expected-note{{in instantiation of}}<br>
+<br>
+#else<br>
+<br>
+template<class T> void foo(T t) { //expected-note{{declared here}}<br>
+  auto L = []()  //expected-note{{begins here}}<br>
+    { return t; }; //expected-error{{cannot be implicitly captured}}<br>
+}<br>
+<br>
+#endif<br>
+}<br>
+<br>
+namespace no_this_capture_for_static {<br>
+<br>
+struct X {<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto lam = [=](auto a) { f(a); };<br>
+    lam(0); // ok.<br>
+    ASSERT_NO_CAPTURES(lam);<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+}<br>
+<br>
+namespace this_capture_for_non_static {<br>
+<br>
+struct X {<br>
+  void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) { f(a); };<br>
+    L(0);<br>
+    auto L2 = [](auto a) { f(a); }; //expected-error {{cannot be implicitly captured}}<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+}<br>
+<br>
+namespace this_captures_with_num_args_disambiguation {<br>
+<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double, int i) { }<br>
+  int g() {<br>
+    auto lam = [](auto a) { f(a, a); };<br>
+    lam(0);<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+}<br>
+namespace enclosing_function_is_template_this_capture {<br>
+// Only error if the instantiation tries to use the member function.<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+  template<class T><br>
+  int g(T t) {<br>
+    auto L = [](auto a) { f(a); }; //expected-error{{'this'}}<br>
+    L(t); // expected-note{{in instantiation of}}<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g(0.0); // OK.<br>
+int run2 = X{}.g(0);  // expected-note{{in instantiation of}}<br>
+<br>
+<br>
+}<br>
+<br>
+namespace enclosing_function_is_template_this_capture_2 {<br>
+// This should error, even if not instantiated, since<br>
+// this would need to be captured.<br>
+struct X {<br>
+  void f(int) { }<br>
+  template<class T><br>
+  int g(T t) {<br>
+    auto L = [](auto a) { f(a); }; //expected-error{{'this'}}<br>
+    L(t);<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+}<br>
+<br>
+<br>
+namespace enclosing_function_is_template_this_capture_3 {<br>
+// This should not error, this does not need to be captured.<br>
+struct X {<br>
+  static void f(int) { }<br>
+  template<class T><br>
+  int g(T t) {<br>
+    auto L = [](auto a) { f(a); };<br>
+    L(t);<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g(0.0); // OK.<br>
+int run2 = X{}.g(0);  // OK.<br>
+<br>
+}<br>
+<br>
+namespace nested_this_capture_1 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [this]() {<br>
+        return [=](auto b) {<br>
+          f(b);<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0);<br>
+    auto N = M();<br>
+    N(5);<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+<br>
+}<br>
+<br>
+<br>
+namespace nested_this_capture_2 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [&]() {<br>
+        return [=](auto b) {<br>
+          f(b);<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0);<br>
+    auto N = M();<br>
+    N(5);<br>
+    N(3.14);<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+<br>
+}<br>
+<br>
+namespace nested_this_capture_3_1 {<br>
+struct X {<br>
+  template<class T><br>
+  void f(int, T t) { }<br>
+  template<class T><br>
+  static void f(double, T t) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [&](auto c) {<br>
+        return [=](auto b) {<br>
+          f(b, c);<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0);<br>
+    auto N = M('a');<br>
+    N(5);<br>
+    N(3.14);<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+<br>
+}<br>
+<br>
+<br>
+namespace nested_this_capture_3_2 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [=](auto a) {<br>
+      return [](int i) {<br>
+        return [=](auto b) {<br>
+          f(b); //expected-error {{'this' cannot}}<br>
+          int x = i;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0.0);<br>
+    auto N = M(3);<br>
+    N(5); //expected-note {{in instantiation of}}<br>
+    N(3.14); // OK.<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+<br>
+}<br>
+<br>
+namespace nested_this_capture_4 {<br>
+struct X {<br>
+  void f(int) { }<br>
+  static void f(double) { }<br>
+<br>
+  int g() {<br>
+    auto L = [](auto a) {<br>
+      return [=](auto i) {<br>
+        return [=](auto b) {<br>
+          f(b); //expected-error {{'this' cannot}}<br>
+          int x = i;<br>
+        };<br>
+      };<br>
+    };<br>
+    auto M = L(0.0);<br>
+    auto N = M(3);<br>
+    N(5); //expected-note {{in instantiation of}}<br>
+    N(3.14); // OK.<br>
+    return 0;<br>
+  }<br>
+};<br>
+<br>
+int run = X{}.g();<br>
+<br>
+}<br>
+namespace capture_enclosing_function_parameters {<br>
+<br>
+<br>
+inline auto foo(int x) {<br>
+  int i = 10;<br>
+  auto lambda = [=](auto z) { return x + z; };<br>
+  return lambda;<br>
+}<br>
+<br>
+int foo2() {<br>
+  auto L = foo(3);<br>
+  L(4);<br>
+  L('a');<br>
+  L(3.14);<br>
+  return 0;<br>
+}<br>
+<br>
+inline auto foo3(int x) {<br>
+  int local = 1;<br>
+  auto L = [=](auto a) {<br>
+        int i = a[local];<br>
+        return  [=](auto b) mutable {<br>
+          auto n = b;<br>
+          return [&, n](auto c) mutable {<br>
+            ++local;<br>
+            return ++x;<br>
+          };<br>
+        };<br>
+  };<br>
+  auto M = L("foo-abc");<br>
+  auto N = M("foo-def");<br>
+  auto O = N("foo-ghi");<br>
+<br>
+  return L;<br>
+}<br>
+<br>
+int main() {<br>
+  auto L3 = foo3(3);<br>
+  auto M3 = L3("L3-1");<br>
+  auto N3 = M3("M3-1");<br>
+  auto O3 = N3("N3-1");<br>
+  N3("N3-2");<br>
+  M3("M3-2");<br>
+  M3("M3-3");<br>
+  L3("L3-2");<br>
+}<br>
+} // end ns<br>
+<br>
+namespace capture_arrays {<br>
+<br>
+inline int sum_array(int n) {<br>
+  int array2[5] = { 1, 2, 3, 4, 5};<br>
+<br>
+  auto L = [=](auto N) -> int {<br>
+    int sum = 0;<br>
+    int array[5] = { 1, 2, 3, 4, 5 };<br>
+    sum += array2[sum];<br>
+    sum += array2[N];<br>
+    return 0;<br>
+  };<br>
+  L(2);<br>
+  return L(n);<br>
+}<br>
+}<br>
+<br>
+namespace capture_non_odr_used_variable_because_named_in_instantiation_dependent_expressions {<br>
+<br>
+// even though 'x' is not odr-used, it should be captured.<br>
+<br>
+int test() {<br>
+  const int x = 10;<br>
+  auto L = [=](auto a) {<br>
+    (void) +x + a;<br>
+  };<br>
+  ASSERT_CLOSURE_SIZE_EXACT(L, sizeof(x));<br>
+}<br>
+<br>
+} //end ns<br>
+#ifdef MS_EXTENSIONS<br>
+namespace explicit_spec {<br>
+template<class R> struct X {<br>
+  template<class T> int foo(T t) {<br>
+    auto L = [](auto a) { return a; };<br>
+    L(&t);<br>
+    return 0;<br>
+  }<br>
+<br>
+  template<> int foo<char>(char c) { //expected-warning{{explicit specialization}}<br>
+    const int x = 10;<br>
+    auto LC = [](auto a) { return a; };<br>
+    R r;<br>
+    LC(&r);<br>
+    auto L = [=](auto a) {<br>
+      return [=](auto b) {<br>
+        int d[sizeof(a)];<br>
+        f(x, d);<br>
+      };<br>
+    };<br>
+    auto M = L(1);<br>
+<br>
+    ASSERT_NO_CAPTURES(M);<br>
+    return 0;<br>
+  }<br>
+<br>
+};<br>
+<br>
+int run_char = X<int>{}.foo('a');<br>
+int run_int = X<double>{}.foo(4);<br>
+}<br>
+<br>
+#endif // MS_EXTENSIONS<br>
+<br>
<br>
Modified: cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp?rev=194188&r1=194187&r2=194188&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp?rev=194188&r1=194187&r2=194188&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/cxx1y-generic-lambdas.cpp Wed Nov  6 23:17:06 2013<br>
@@ -12,6 +12,108 @@ int test() {<br>
 }<br>
 } //end ns<br>
<br>
+namespace test_conversion_to_fptr_2 {<br>
+<br>
+template<class T> struct X {<br>
+<br>
+  T (*fp)(T) = [](auto a) { return a; };<br>
+<br>
+};<br>
+<br>
+X<int> xi;<br>
+<br>
+template<class T><br>
+void fooT(T t, T (*fp)(T) = [](auto a) { return a; }) {<br>
+  fp(t);<br>
+}<br>
+<br>
+int test() {<br>
+{<br>
+  auto L = [](auto a) { return a; };<br>
+  int (*fp)(int) = L;<br>
+  fp(5);<br>
+  L(3);<br>
+  char (*fc)(char) = L;<br>
+  fc('b');<br>
+  L('c');<br>
+  double (*fd)(double) = L;<br>
+  fd(3.14);<br>
+  fd(6.26);<br>
+  L(4.25);<br>
+}<br>
+{<br>
+  auto L = [](auto a) ->int { return a; }; //expected-note 2{{candidate template ignored}}<br>
+  int (*fp)(int) = L;<br>
+  char (*fc)(char) = L; //expected-error{{no viable conversion}}<br>
+  double (*fd)(double) = L; //expected-error{{no viable conversion}}<br>
+}<br>
+{<br>
+  int x = 5;<br>
+  auto L = [=](auto b, char c = 'x') {<br>
+    int i = x;<br>
+    return [](auto a) ->decltype(a) { return a; };<br>
+  };<br>
+  int (*fp)(int) = L(8);<br>
+  fp(5);<br>
+  L(3);<br>
+  char (*fc)(char) = L('a');<br>
+  fc('b');<br>
+  L('c');<br>
+  double (*fd)(double) = L(3.14);<br>
+  fd(3.14);<br>
+  fd(6.26);<br>
+<br>
+}<br>
+{<br>
+ auto L = [=](auto b) {<br>
+    return [](auto a) ->decltype(b)* { return (decltype(b)*)0; };<br>
+  };<br>
+  int* (*fp)(int) = L(8);<br>
+  fp(5);<br>
+  L(3);<br>
+  char* (*fc)(char) = L('a');<br>
+  fc('b');<br>
+  L('c');<br>
+  double* (*fd)(double) = L(3.14);<br>
+  fd(3.14);<br>
+  fd(6.26);<br>
+}<br>
+{<br>
+ auto L = [=](auto b) {<br>
+    return [](auto a) ->decltype(b)* { return (decltype(b)*)0; }; //expected-note{{candidate template ignored}}<br>
+  };<br>
+  char* (*fp)(int) = L('8');<br>
+  fp(5);<br>
+  char* (*fc)(char) = L('a');<br>
+  fc('b');<br>
+  double* (*fi)(int) = L(3.14);<br>
+  fi(5);<br>
+  int* (*fi2)(int) = L(3.14); //expected-error{{no viable conversion}}<br>
+}<br>
+<br>
+{<br>
+ auto L = [=](auto b) {<br>
+    return [](auto a) {<br>
+      return [=](auto c) {<br>
+        return [](auto d) ->decltype(a + b + c + d) { return d; };<br>
+      };<br>
+    };<br>
+  };<br>
+  int (*fp)(int) = L('8')(3)(short{});<br>
+  double (*fs)(char) = L(3.14)(short{})('4');<br>
+}<br>
+<br>
+  fooT(3);<br>
+  fooT('a');<br>
+  fooT(3.14);<br>
+  fooT("abcdefg");<br>
+  return 0;<br>
+}<br>
+int run2 = test();<br>
+<br>
+}<br>
+<br>
+<br>
 namespace test_conversion_to_fptr {<br>
<br>
 void f1(int (*)(int)) { }<br>
@@ -129,17 +231,26 @@ int test() {<br>
   M(4.15);<br>
  }<br>
 {<br>
-  int i = 10; //expected-note{{declared here}}<br>
+  int i = 10; //expected-note 3{{declared here}}<br>
   auto L = [](auto a) {<br>
-    return [](auto b) { //expected-note{{begins here}}<br>
-      i = b;  //expected-error{{cannot be implicitly captured}}<br>
+    return [](auto b) { //expected-note 3{{begins here}}<br>
+      i = b;  //expected-error 3{{cannot be implicitly captured}}<br>
       return b;<br>
     };<br>
   };<br>
-  auto M = L(3);<br>
+  auto M = L(3); //expected-note{{instantiation}}<br>
   M(4.15); //expected-note{{instantiation}}<br>
  }<br>
  {<br>
+  int i = 10;<br>
+  auto L = [](auto a) {<br>
+    return [](auto b) {<br>
+      b = sizeof(i);  //ok<br>
+      return b;<br>
+    };<br>
+  };<br>
+ }<br>
+ {<br>
   auto L = [](auto a) {<br>
     print("a = ", a, "\n");<br>
     return [](auto b) ->decltype(a) {<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>