summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaLambda.cpp
diff options
context:
space:
mode:
authorFaisal Vali <faisalv@yahoo.com>2016-03-26 16:11:37 +0000
committerFaisal Vali <faisalv@yahoo.com>2016-03-26 16:11:37 +0000
commita734ab9808658310b63e5a945f21837076dd14c7 (patch)
tree0261e163817fe9adae255dec91c851dc2f4793c6 /clang/lib/Sema/SemaLambda.cpp
parente4dbeb40c6a08abb5486c25ab0b31926f10d6248 (diff)
downloadbcm5719-llvm-a734ab9808658310b63e5a945f21837076dd14c7.tar.gz
bcm5719-llvm-a734ab9808658310b63e5a945f21837076dd14c7.zip
[Cxx1z-constexpr-lambda-P0170R1] Support parsing of constexpr specifier (and its inference) on lambda expressions
Support the constexpr specifier on lambda expressions - and support its inference from the lambda call operator's body. i.e. auto L = [] () constexpr { return 5; }; static_assert(L() == 5); // OK auto Implicit = [] (auto a) { return a; }; static_assert(Implicit(5) == 5); We do not support evaluation of lambda's within constant expressions just yet. Implementation Strategy: - teach ParseLambdaExpressionAfterIntroducer to expect a constexpr specifier and mark the invented function call operator's declarator's decl-specifier with it; Have it emit fixits for multiple decl-specifiers (mutable or constexpr) in this location. - for cases where constexpr is not explicitly specified, have buildLambdaExpr check whether the invented function call operator satisfies the requirements of a constexpr function, by calling CheckConstexprFunctionDecl/Body. Much obliged to Richard Smith for his patience and his care, in ensuring the code is clang-worthy. llvm-svn: 264513
Diffstat (limited to 'clang/lib/Sema/SemaLambda.cpp')
-rw-r--r--clang/lib/Sema/SemaLambda.cpp21
1 files changed, 17 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 1dd37bd2d26..88754e25975 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -355,7 +355,8 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
SourceRange IntroducerRange,
TypeSourceInfo *MethodTypeInfo,
SourceLocation EndLoc,
- ArrayRef<ParmVarDecl *> Params) {
+ ArrayRef<ParmVarDecl *> Params,
+ const bool IsConstexprSpecified) {
QualType MethodType = MethodTypeInfo->getType();
TemplateParameterList *TemplateParams =
getGenericLambdaTemplateParameterList(getCurLambda(), *this);
@@ -392,7 +393,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
MethodType, MethodTypeInfo,
SC_None,
/*isInline=*/true,
- /*isConstExpr=*/false,
+ IsConstexprSpecified,
EndLoc);
Method->setAccess(AS_public);
@@ -879,8 +880,9 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo,
KnownDependent, Intro.Default);
- CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
- MethodTyInfo, EndLoc, Params);
+ CXXMethodDecl *Method =
+ startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params,
+ ParamInfo.getDeclSpec().isConstexprSpecified());
if (ExplicitParams)
CheckCXXDefaultArguments(Method);
@@ -1600,6 +1602,17 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc,
CaptureInits, ArrayIndexVars,
ArrayIndexStarts, EndLoc,
ContainsUnexpandedParameterPack);
+ // If the lambda expression's call operator is not explicitly marked constexpr
+ // and we are not in a dependent context, analyze the call operator to infer
+ // its constexpr-ness, supressing diagnostics while doing so.
+ if (getLangOpts().CPlusPlus1z && !CallOperator->isInvalidDecl() &&
+ !CallOperator->isConstexpr() &&
+ !Class->getDeclContext()->isDependentContext()) {
+ TentativeAnalysisScope DiagnosticScopeGuard(*this);
+ CallOperator->setConstexpr(
+ CheckConstexprFunctionDecl(CallOperator) &&
+ CheckConstexprFunctionBody(CallOperator, CallOperator->getBody()));
+ }
if (!CurContext->isDependentContext()) {
switch (ExprEvalContexts.back().Context) {
OpenPOWER on IntegriCloud