Index: include/clang/Basic/DiagnosticASTKinds.td =================================================================== --- include/clang/Basic/DiagnosticASTKinds.td +++ include/clang/Basic/DiagnosticASTKinds.td @@ -162,8 +162,17 @@ // 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!)">; + "unimplemented constexpr lambda feature: %0 (coming soon!)">; +// C++1z constexpr lambda expressions +def warn_cxx14_compat_constexpr_conversion_on_lambda : Warning< + "constexpr conversion to pointer-to-function on lambdas is " + "incompatible with C++ standards before C++1z">, + InGroup, DefaultIgnore; +def ext_constexpr_conversion_on_lambda_cxx1z : ExtWarn< + "constexpr conversion to pointer-to-function on lambdas is " + "a C++1z extension">, InGroup; + // inline asm related. let CategoryName = "Inline Assembly Issue" in { def err_asm_invalid_escape : Error< Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -4353,6 +4353,17 @@ if (!EvaluateObjectArgument(Info, ME->getBase(), ThisVal)) return false; Member = ME->getMemberDecl(); + // If this is a non-capturing lambda's closure type's conversion + // operator that results in a pointer-to-function, remind users that the + // conversion operator itself was made 'constexpr' in C++1z. + if (const CXXConversionDecl *Conv = dyn_cast(Member)) + if (Conv->getParent()->isLambda()) { + Info.Ctx.getDiagnostics().Report( + E->getExprLoc(), + !Info.Ctx.getLangOpts().CPlusPlus1z + ? diag::ext_constexpr_conversion_on_lambda_cxx1z + : diag::warn_cxx14_compat_constexpr_conversion_on_lambda); + } This = &ThisVal; HasQualifier = ME->hasQualifier(); } else if (const BinaryOperator *BE = dyn_cast(Callee)) { Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -1261,7 +1261,7 @@ ConvTy, ConvTSI, /*isInline=*/true, /*isExplicit=*/false, - /*isConstexpr=*/false, + /*isConstexpr=*/true, CallOperator->getBody()->getLocEnd()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); Index: test/SemaCXX/cxx1z-constexpr-lambdas.cpp =================================================================== --- test/SemaCXX/cxx1z-constexpr-lambdas.cpp +++ test/SemaCXX/cxx1z-constexpr-lambdas.cpp @@ -2,7 +2,9 @@ // 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 +// RUN: %clang_cc1 -std=c++1z -verify -fsyntax-only -fblocks -Wc++14-compat %s -DCHECK_COMPATIBILITY_WARNING +#ifndef CHECK_COMPATIBILITY_WARNING namespace test_constexpr_checking { namespace ns1 { @@ -33,4 +35,17 @@ L(3); //expected-note{{non-constexpr function}} } -} // end ns test_constexpr_call \ No newline at end of file +} // end ns test_constexpr_call +#endif + +#ifdef CHECK_COMPATIBILITY_WARNING +//expected-warning@+6{{incompatible with C++ standards before C++1z}} +//expected-warning@+6{{incompatible with C++ standards before C++1z}} +#endif + +namespace ns4 { +auto L = [](auto a) { return a; }; +constexpr int (*fp1)(int) = L; +constexpr int* (*fp2)(int*) = L; + +} // end ns4 \ No newline at end of file