Index: include/clang/Basic/DiagnosticASTKinds.td =================================================================== --- include/clang/Basic/DiagnosticASTKinds.td +++ include/clang/Basic/DiagnosticASTKinds.td @@ -158,12 +158,6 @@ "overflow in expression; result is %0 with type %1">, InGroup>; -// This is a temporary diagnostic, and shall be removed once our -// implementation is complete, and like the preceding constexpr notes belongs -// in Sema. -def note_unimplemented_constexpr_lambda_feature_ast : Note< - "unimplemented constexpr lambda feature: %0 (coming soon!)">; - // inline asm related. let CategoryName = "Inline Assembly Issue" in { def err_asm_invalid_escape : Error< Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -780,20 +780,11 @@ InGroup, DefaultIgnore; def err_lambda_missing_parens : Error< "lambda requires '()' before %select{'mutable'|return type|" - "attribute specifier|'constexpr'}0">; -def err_lambda_decl_specifier_repeated : Error< - "%select{'mutable'|'constexpr'}0 cannot appear multiple times in a lambda declarator">; + "attribute specifier}0">; // C++1z lambda expressions def err_expected_star_this_capture : Error< "expected 'this' following '*' in lambda capture list">; -// C++1z constexpr lambda expressions -def warn_cxx14_compat_constexpr_on_lambda : Warning< - "constexpr on lambda expressions is incompatible with C++ standards before C++1z">, - InGroup, DefaultIgnore; -def ext_constexpr_on_lambda_cxx1z : ExtWarn< - "'constexpr' on lambda expressions is a C++1z extension">, InGroup; - // Availability attribute def err_expected_version : Error< "expected a version of the form 'major[.minor[.subminor]]'">; Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -5111,8 +5111,7 @@ SourceRange IntroducerRange, TypeSourceInfo *MethodType, SourceLocation EndLoc, - ArrayRef Params, - bool IsConstexprSpecified); + ArrayRef Params); /// \brief Endow the lambda scope info with the relevant properties. void buildLambdaScope(sema::LambdaScopeInfo *LSI, Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -36,7 +36,6 @@ #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTDiagnostic.h" -#include "clang/AST/ASTLambda.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Expr.h" #include "clang/AST/RecordLayout.h" @@ -2126,22 +2125,7 @@ // If this is a local variable, dig out its value. if (Frame) { Result = Frame->getTemporary(VD); - if (!Result) { - // Assume variables referenced within a lambda's call operator that were - // not declared within the call operator are captures and during checking - // of a potential constant expression, assume they are unknown constant - // expressions. - assert(isLambdaCallOperator(Frame->Callee) && - (VD->getDeclContext() != Frame->Callee || VD->isInitCapture()) && - "missing value for local variable"); - if (Info.checkingPotentialConstantExpression()) - return false; - // FIXME: implement capture evaluation during constant expr evaluation. - Info.FFDiag(E->getLocStart(), - diag::note_unimplemented_constexpr_lambda_feature_ast) - << "captures not currently allowed"; - return false; - } + assert(Result && "missing value for local variable"); return true; } Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -1053,58 +1053,6 @@ return false; } -static void -tryConsumeMutableOrConstexprToken(Parser &P, SourceLocation &MutableLoc, - SourceLocation &ConstexprLoc, - SourceLocation &DeclEndLoc) { - assert(MutableLoc.isInvalid()); - assert(ConstexprLoc.isInvalid()); - // Consume constexpr-opt mutable-opt in any sequence, and set the DeclEndLoc - // to the final of those locations. Emit an error if we have multiple - // copies of those keywords and recover. - - while (true) { - switch (P.getCurToken().getKind()) { - case tok::kw_mutable: { - if (MutableLoc.isValid()) { - P.Diag(P.getCurToken().getLocation(), - diag::err_lambda_decl_specifier_repeated) - << 0 << FixItHint::CreateRemoval(P.getCurToken().getLocation()); - } - MutableLoc = P.ConsumeToken(); - DeclEndLoc = MutableLoc; - break /*switch*/; - } - case tok::kw_constexpr: - if (ConstexprLoc.isValid()) { - P.Diag(P.getCurToken().getLocation(), - diag::err_lambda_decl_specifier_repeated) - << 1 << FixItHint::CreateRemoval(P.getCurToken().getLocation()); - } - ConstexprLoc = P.ConsumeToken(); - DeclEndLoc = ConstexprLoc; - break /*switch*/; - default: - return; - } - } -} - -static void -addConstexprToLambdaDeclSpecifier(Parser &P, SourceLocation ConstexprLoc, - DeclSpec &DS) { - if (ConstexprLoc.isValid()) { - P.Diag(ConstexprLoc, !P.getLangOpts().CPlusPlus1z - ? diag::ext_constexpr_on_lambda_cxx1z - : diag::warn_cxx14_compat_constexpr_on_lambda); - const char *PrevSpec = nullptr; - unsigned DiagID = 0; - DS.SetConstexprSpec(ConstexprLoc, PrevSpec, DiagID); - assert(PrevSpec == nullptr && DiagID == 0 && - "Constexpr cannot have been set previously!"); - } -} - /// ParseLambdaExpressionAfterIntroducer - Parse the rest of a lambda /// expression. ExprResult Parser::ParseLambdaExpressionAfterIntroducer( @@ -1163,13 +1111,10 @@ // compatible with MSVC. MaybeParseMicrosoftDeclSpecs(Attr, &DeclEndLoc); - // Parse mutable-opt and/or constexpr-opt, and update the DeclEndLoc. + // Parse 'mutable'[opt]. SourceLocation MutableLoc; - SourceLocation ConstexprLoc; - tryConsumeMutableOrConstexprToken(*this, MutableLoc, ConstexprLoc, - DeclEndLoc); - - addConstexprToLambdaDeclSpecifier(*this, ConstexprLoc, DS); + if (TryConsumeToken(tok::kw_mutable, MutableLoc)) + DeclEndLoc = MutableLoc; // Parse exception-specification[opt]. ExceptionSpecificationType ESpecType = EST_None; @@ -1227,8 +1172,7 @@ LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), Attr, DeclEndLoc); - } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute, - tok::kw_constexpr) || + } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute) || (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) { // It's common to forget that one needs '()' before 'mutable', an attribute // specifier, or the result type. Deal with this. @@ -1238,7 +1182,6 @@ case tok::arrow: TokKind = 1; break; case tok::kw___attribute: case tok::l_square: TokKind = 2; break; - case tok::kw_constexpr: TokKind = 3; break; default: llvm_unreachable("Unknown token kind"); } Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -355,8 +355,7 @@ SourceRange IntroducerRange, TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc, - ArrayRef Params, - const bool IsConstexprSpecified) { + ArrayRef Params) { QualType MethodType = MethodTypeInfo->getType(); TemplateParameterList *TemplateParams = getGenericLambdaTemplateParameterList(getCurLambda(), *this); @@ -393,7 +392,7 @@ MethodType, MethodTypeInfo, SC_None, /*isInline=*/true, - IsConstexprSpecified, + /*isConstExpr=*/false, EndLoc); Method->setAccess(AS_public); @@ -878,9 +877,8 @@ CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, KnownDependent, Intro.Default); - CXXMethodDecl *Method = - startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params, - ParamInfo.getDeclSpec().isConstexprSpecified()); + CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, + MethodTyInfo, EndLoc, Params); if (ExplicitParams) CheckCXXDefaultArguments(Method); @@ -1599,17 +1597,6 @@ 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) { Index: lib/Sema/TreeTransform.h =================================================================== --- lib/Sema/TreeTransform.h +++ lib/Sema/TreeTransform.h @@ -10222,9 +10222,7 @@ CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition( Class, E->getIntroducerRange(), NewCallOpTSI, E->getCallOperator()->getLocEnd(), - NewCallOpTSI->getTypeLoc().castAs().getParams(), - E->getCallOperator()->isConstexpr()); - + NewCallOpTSI->getTypeLoc().castAs().getParams()); LSI->CallOperator = NewCallOperator; getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); Index: test/Parser/cxx1z-constexpr-lambdas.cpp =================================================================== --- test/Parser/cxx1z-constexpr-lambdas.cpp +++ test/Parser/cxx1z-constexpr-lambdas.cpp @@ -1,31 +0,0 @@ -// RUN: %clang_cc1 -std=c++1z %s -verify -// RUN: %clang_cc1 -std=c++14 %s -verify -// RUN: %clang_cc1 -std=c++11 %s -verify - - -auto XL0 = [] constexpr { }; //expected-error{{requires '()'}} expected-error{{expected body}} -auto XL1 = [] () mutable - mutable //expected-error{{cannot appear multiple times}} - mutable { }; //expected-error{{cannot appear multiple times}} - -#if __cplusplus > 201402L -auto XL2 = [] () constexpr mutable constexpr { }; //expected-error{{cannot appear multiple times}} -auto L = []() mutable constexpr { }; -auto L2 = []() constexpr { }; -auto L4 = []() constexpr mutable { }; -auto XL16 = [] () constexpr - mutable - constexpr //expected-error{{cannot appear multiple times}} - mutable //expected-error{{cannot appear multiple times}} - mutable //expected-error{{cannot appear multiple times}} - constexpr //expected-error{{cannot appear multiple times}} - constexpr //expected-error{{cannot appear multiple times}} - { }; - -#else -auto L = []() mutable constexpr {return 0; }; //expected-warning{{is a C++1z extension}} -auto L2 = []() constexpr { return 0;};//expected-warning{{is a C++1z extension}} -auto L4 = []() constexpr mutable { return 0; }; //expected-warning{{is a C++1z extension}} -#endif - - Index: test/SemaCXX/cxx1z-constexpr-lambdas.cpp =================================================================== --- test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -1,36 +0,0 @@ -// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks %s -// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fms-extensions %s -// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s - -namespace test_constexpr_checking { - -namespace ns1 { - struct NonLit { ~NonLit(); }; //expected-note{{not literal}} - auto L = [](NonLit NL) constexpr { }; //expected-error{{not a literal type}} -} // end ns1 - -namespace ns2 { - auto L = [](int I) constexpr { asm("non-constexpr"); }; //expected-error{{not allowed in constexpr function}} -} // end ns1 - -} // end ns test_constexpr_checking - -namespace test_constexpr_call { - -namespace ns1 { - auto L = [](int I) { return I; }; - static_assert(L(3) == 3); -} // end ns1 -namespace ns2 { - auto L = [](auto a) { return a; }; - static_assert(L(3) == 3); - static_assert(L(3.14) == 3.14); -} -namespace ns3 { - auto L = [](auto a) { asm("non-constexpr"); return a; }; //expected-note{{declared here}} - constexpr int I = //expected-error{{must be initialized by a constant expression}} - L(3); //expected-note{{non-constexpr function}} -} - -} // end ns test_constexpr_call \ No newline at end of file