Introduce basic ASTs for lambda expressions. This covers:
  - Capturing variables by-reference and by-copy within a lambda
  - The representation of lambda captures
  - The creation of the non-static data members in the lambda class
  that store the captured variables
  - The initialization of the non-static data members from the
  captured variables
  - Pretty-printing lambda expressions

There are a number of FIXMEs, both explicit and implied, including:
  - Creating a field for a capture of 'this'
  - Improved diagnostics for initialization failures when capturing
  variables by copy
  - Dealing with temporaries created during said initialization
  - Template instantiation
  - AST (de-)serialization
  - Binding and returning the lambda expression; turning it into a
  proper temporary
  - Lots and lots of semantic constraints
  - Parameter pack captures


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149977 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 8738e5f..f2ebd8c 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -2019,6 +2019,16 @@
     return MergeCanThrow(CT, CanSubExprsThrow(C, this));
   }
 
+  case LambdaExprClass: {
+    const LambdaExpr *Lambda = cast<LambdaExpr>(this);
+    CanThrowResult CT = Expr::CT_Cannot;
+    for (LambdaExpr::capture_init_iterator Cap = Lambda->capture_init_begin(),
+                                        CapEnd = Lambda->capture_init_end();
+         Cap != CapEnd; ++Cap)
+      CT = MergeCanThrow(CT, (*Cap)->CanThrow(C));
+    return CT;
+  }
+
   case CXXNewExprClass: {
     CanThrowResult CT;
     if (isTypeDependent())
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index df223eb..51dd57c 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -712,6 +712,113 @@
   }
 }
 
+LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit,
+                             LambdaCaptureKind Kind, VarDecl *Var,
+                             SourceLocation EllipsisLoc)
+  : VarAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
+{
+  unsigned Bits = 0;
+  if (Implicit)
+    Bits |= Capture_Implicit;
+  
+  switch (Kind) {
+  case LCK_This: 
+    assert(Var == 0 && "'this' capture cannot have a variable!");
+    break;
+
+  case LCK_ByCopy:
+    Bits |= Capture_ByCopy;
+    // Fall through 
+  case LCK_ByRef:
+    assert(Var && "capture must have a variable!");
+    break;
+  }
+  VarAndBits.setInt(Bits);
+}
+
+LambdaCaptureKind LambdaExpr::Capture::getCaptureKind() const {
+  if (capturesThis())
+    return LCK_This;
+
+  return (VarAndBits.getInt() & Capture_ByCopy)? LCK_ByCopy : LCK_ByRef;
+}
+
+LambdaExpr::LambdaExpr(QualType T, 
+                       SourceRange IntroducerRange,
+                       LambdaCaptureDefault CaptureDefault,
+                       ArrayRef<Capture> Captures, 
+                       bool ExplicitParams,
+                       ArrayRef<Expr *> CaptureInits,
+                       SourceLocation ClosingBrace)
+  : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary,
+         T->isDependentType(), T->isDependentType(), T->isDependentType(),
+         /*ContainsUnexpandedParameterPack=*/false),
+    IntroducerRange(IntroducerRange),
+    NumCaptures(Captures.size()),
+    NumExplicitCaptures(0),
+    CaptureDefault(CaptureDefault),
+    ExplicitParams(ExplicitParams),
+    ClosingBrace(ClosingBrace)
+{
+  assert(CaptureInits.size() == Captures.size() && "Wrong number of arguments");
+
+  // Copy captures.
+  // FIXME: Do we need to update "contains unexpanded parameter pack" here?
+  Capture *ToCapture = reinterpret_cast<Capture *>(this + 1);
+  for (unsigned I = 0, N = Captures.size(); I != N; ++I) {
+    if (Captures[I].isExplicit())
+      ++NumExplicitCaptures;
+    *ToCapture++ = Captures[I];
+  }
+
+  // Copy initialization expressions for the non-static data members.
+  Stmt **Stored = getStoredStmts();
+  for (unsigned I = 0, N = CaptureInits.size(); I != N; ++I)
+    *Stored++ = CaptureInits[I];
+
+  // Copy the body of the lambda.
+  *Stored++ = getCallOperator()->getBody();
+}
+
+LambdaExpr *LambdaExpr::Create(ASTContext &Context, 
+                               CXXRecordDecl *Class,
+                               SourceRange IntroducerRange,
+                               LambdaCaptureDefault CaptureDefault,
+                               ArrayRef<Capture> Captures, 
+                               bool ExplicitParams,
+                               ArrayRef<Expr *> CaptureInits,
+                               SourceLocation ClosingBrace) {
+  // Determine the type of the expression (i.e., the type of the
+  // function object we're creating).
+  QualType T = Context.getTypeDeclType(Class);
+  size_t Size = sizeof(LambdaExpr) + sizeof(Capture) * Captures.size()
+              + sizeof(Stmt *) * (Captures.size() + 1);
+
+  void *Mem = Context.Allocate(Size, llvm::alignOf<LambdaExpr>());
+  return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, 
+                              Captures, ExplicitParams, CaptureInits,
+                              ClosingBrace);
+}
+
+CXXRecordDecl *LambdaExpr::getLambdaClass() const {
+  return getType()->getAsCXXRecordDecl();
+}
+
+CXXMethodDecl *LambdaExpr::getCallOperator() const {
+  CXXRecordDecl *Record = getLambdaClass();
+  DeclarationName Name
+    = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclContext::lookup_result Calls = Record->lookup(Name);
+  assert(Calls.first != Calls.second && "Missing lambda call operator!");
+  CXXMethodDecl *Result = cast<CXXMethodDecl>(*Calls.first++);
+  assert(Calls.first == Calls.second && "More than lambda one call operator?");
+  return Result;
+}
+
+bool LambdaExpr::isMutable() const {
+  return (getCallOperator()->getTypeQualifiers() & Qualifiers::Const) == 0;
+}
+
 ExprWithCleanups::ExprWithCleanups(Expr *subexpr,
                                    ArrayRef<CleanupObject> objects)
   : Expr(ExprWithCleanupsClass, subexpr->getType(),
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index 311b805..79d8dc4 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -330,6 +330,7 @@
     // Some C++ expressions are always class temporaries.
   case Expr::CXXConstructExprClass:
   case Expr::CXXTemporaryObjectExprClass:
+  case Expr::LambdaExprClass:
     return Cl::CL_ClassTemporary;
 
   case Expr::VAArgExprClass:
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index bb7042d..283132a 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -6086,6 +6086,7 @@
   case Expr::PseudoObjectExprClass:
   case Expr::AtomicExprClass:
   case Expr::InitListExprClass:
+  case Expr::LambdaExprClass:
     return ICEDiag(2, E->getLocStart());
 
   case Expr::SizeOfPackExprClass:
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index 37ae626..e39031d 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -2247,6 +2247,7 @@
   case Expr::ImplicitValueInitExprClass:
   case Expr::InitListExprClass:
   case Expr::ParenListExprClass:
+  case Expr::LambdaExprClass:
     llvm_unreachable("unexpected statement kind");
 
   // FIXME: invent manglings for all these.
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 7077be1..1e2a494 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1263,6 +1263,98 @@
   OS << ")";
 }
 
+void StmtPrinter::VisitLambdaExpr(LambdaExpr *Node) {
+  OS << '[';
+  bool NeedComma = false;
+  switch (Node->getCaptureDefault()) {
+  case LCD_None:
+    break;
+
+  case LCD_ByCopy:
+    OS << '=';
+    NeedComma = true;
+    break;
+
+  case LCD_ByRef:
+    OS << '&';
+    NeedComma = true;
+    break;
+  }
+  for (LambdaExpr::capture_iterator C = Node->explicit_capture_begin(),
+                                 CEnd = Node->explicit_capture_end();
+       C != CEnd;
+       ++C) {
+    if (NeedComma)
+      OS << ", ";
+    NeedComma = true;
+
+    switch (C->getCaptureKind()) {
+    case LCK_This:
+      OS << "this";
+      break;
+
+    case LCK_ByRef:
+      if (Node->getCaptureDefault() != LCD_ByRef)
+        OS << '&';
+      OS << C->getCapturedVar()->getName();
+      break;
+
+    case LCK_ByCopy:
+      if (Node->getCaptureDefault() != LCD_ByCopy)
+        OS << '=';
+      OS << C->getCapturedVar()->getName();
+      break;
+    }
+  }
+  OS << ']';
+
+  if (Node->hasExplicitParameters()) {
+    OS << " (";
+    CXXMethodDecl *Method = Node->getCallOperator();
+    NeedComma = false;
+    for (CXXMethodDecl::param_iterator P = Method->param_begin(),
+                                    PEnd = Method->param_end();
+         P != PEnd; ++P) {
+      if (NeedComma) {
+        OS << ", ";
+      } else {
+        NeedComma = true;
+      }
+      std::string ParamStr = (*P)->getNameAsString();
+      (*P)->getOriginalType().getAsStringInternal(ParamStr, Policy);
+      OS << ParamStr;
+    }
+    if (Method->isVariadic()) {
+      if (NeedComma)
+        OS << ", ";
+      OS << "...";
+    }
+    OS << ')';
+
+    if (Node->isMutable())
+      OS << " mutable";
+
+    const FunctionProtoType *Proto
+      = Method->getType()->getAs<FunctionProtoType>();
+    {
+      std::string ExceptionSpec;
+      Proto->printExceptionSpecification(ExceptionSpec, Policy);
+      OS << ExceptionSpec;
+    }
+
+    // FIXME: Attributes
+
+    // FIXME: Suppress trailing return type if it wasn't specified in
+    // the source.
+    OS << " -> " << Proto->getResultType().getAsString(Policy);
+  }
+
+  // Print the body.
+  CompoundStmt *Body = Node->getBody();
+  OS << ' ';
+  PrintStmt(Body);
+}
+
 void StmtPrinter::VisitCXXScalarValueInitExpr(CXXScalarValueInitExpr *Node) {
   if (TypeSourceInfo *TSInfo = Node->getTypeSourceInfo())
     OS << TSInfo->getType().getAsString(Policy) << "()";
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 2fb67d9..1d58fd7 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -790,6 +790,24 @@
 }
 
 void
+StmtProfiler::VisitLambdaExpr(const LambdaExpr *S) {
+  VisitExpr(S);
+  for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
+                                 CEnd = S->explicit_capture_end();
+       C != CEnd; ++C) {
+    ID.AddInteger(C->getCaptureKind());
+    if (C->capturesVariable()) {
+      VisitDecl(C->getCapturedVar());
+      ID.AddBoolean(C->isPackExpansion());
+    }
+  }
+  // Note: If we actually needed to be able to match lambda
+  // expressions, we would have to consider parameters and return type
+  // here, among other things.
+  VisitStmt(S->getBody());
+}
+
+void
 StmtProfiler::VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *S) {
   VisitExpr(S);
 }
diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp
index b6d7110..7e9e7c5 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -397,6 +397,35 @@
   print(T->getElementType(), S);
 }
 
+void 
+FunctionProtoType::printExceptionSpecification(std::string &S, 
+                                               PrintingPolicy Policy) const {
+  
+  if (hasDynamicExceptionSpec()) {
+    S += " throw(";
+    if (getExceptionSpecType() == EST_MSAny)
+      S += "...";
+    else
+      for (unsigned I = 0, N = getNumExceptions(); I != N; ++I) {
+        if (I)
+          S += ", ";
+        
+        S += getExceptionType(I).getAsString(Policy);
+      }
+    S += ")";
+  } else if (isNoexceptExceptionSpec(getExceptionSpecType())) {
+    S += " noexcept";
+    if (getExceptionSpecType() == EST_ComputedNoexcept) {
+      S += "(";
+      llvm::raw_string_ostream EOut(S);
+      getNoexceptExpr()->printPretty(EOut, 0, Policy);
+      EOut.flush();
+      S += EOut.str();
+      S += ")";
+    }
+  }
+}
+
 void TypePrinter::printFunctionProto(const FunctionProtoType *T, 
                                      std::string &S) { 
   // If needed for precedence reasons, wrap the inner part in grouping parens.
@@ -470,33 +499,7 @@
     S += " &&";
     break;
   }
-
-  if (T->hasDynamicExceptionSpec()) {
-    S += " throw(";
-    if (T->getExceptionSpecType() == EST_MSAny)
-      S += "...";
-    else
-      for (unsigned I = 0, N = T->getNumExceptions(); I != N; ++I) {
-        if (I)
-          S += ", ";
-
-        std::string ExceptionType;
-        print(T->getExceptionType(I), ExceptionType);
-        S += ExceptionType;
-      }
-    S += ")";
-  } else if (isNoexceptExceptionSpec(T->getExceptionSpecType())) {
-    S += " noexcept";
-    if (T->getExceptionSpecType() == EST_ComputedNoexcept) {
-      S += "(";
-      llvm::raw_string_ostream EOut(S);
-      T->getNoexceptExpr()->printPretty(EOut, 0, Policy);
-      EOut.flush();
-      S += EOut.str();
-      S += ")";
-    }
-  }
-
+  T->printExceptionSpecification(S, Policy);
   print(T->getResultType(), S);
 }