diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/Expr.cpp | 10 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 107 | ||||
-rw-r--r-- | lib/AST/ExprClassification.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 1 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 1 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 92 | ||||
-rw-r--r-- | lib/AST/StmtProfile.cpp | 18 | ||||
-rw-r--r-- | lib/AST/TypePrinter.cpp | 57 |
8 files changed, 260 insertions, 27 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 8738e5f885..f2ebd8cf48 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2019,6 +2019,16 @@ Expr::CanThrowResult Expr::CanThrow(ASTContext &C) const { 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 df223eb32c..51dd57cfe3 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -712,6 +712,113 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, } } +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 311b805471..79d8dc48fe 100644 --- a/lib/AST/ExprClassification.cpp +++ b/lib/AST/ExprClassification.cpp @@ -330,6 +330,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) { // 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 bb7042d195..283132a356 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -6086,6 +6086,7 @@ static ICEDiag CheckICE(const Expr* E, ASTContext &Ctx) { 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 37ae626683..e39031dced 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2247,6 +2247,7 @@ recurse: 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 7077be1d93..1e2a494daa 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1263,6 +1263,98 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { 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 2fb67d93a6..1d58fd7b2b 100644 --- a/lib/AST/StmtProfile.cpp +++ b/lib/AST/StmtProfile.cpp @@ -790,6 +790,24 @@ StmtProfiler::VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *S) { } 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 b6d71108bd..7e9e7c59b1 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -397,6 +397,35 @@ void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) { 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 @@ void TypePrinter::printFunctionProto(const FunctionProtoType *T, 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); } |