Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -4386,6 +4386,10 @@ Call.getLValueBase().dyn_cast()); if (!FD) return Error(Callee); + + // Don't call function pointers which have been cast to some other type. + if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType())) + return Error(E); // Overloaded operator calls to member functions are represented as normal // calls with '*this' as the first argument. @@ -4401,11 +4405,36 @@ return false; This = &ThisVal; Args = Args.slice(1); + } else if (MD && MD->isLambdaStaticInvoker()) { + + // Map the static invoker for the lambda back to the call operator. + // Conveniently, we don't have to slice out the 'this' argument (as is + // being done for the non-static case), since a static member function + // doesn't have an implicit argument passed in. + const CXXRecordDecl *ClosureClass = MD->getParent(); + // number of captures better be zero. + assert(std::distance(ClosureClass->captures_begin(), + ClosureClass->captures_end()) == 0); + const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator(); + + // Set 'FD', the function that will be called below, to the call + // operator. If the closure object represents a generic lambda, find + // the corresponding specialization of the call operator. + + if (ClosureClass->isGenericLambda()) { + assert(MD->isFunctionTemplateSpecialization()); + const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs(); + FunctionTemplateDecl *CallOpTemplate = + LambdaCallOp->getDescribedFunctionTemplate(); + void *InsertPos = nullptr; + FunctionDecl *CorrespondingCallOpSpecialization = + CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos); + assert(CorrespondingCallOpSpecialization); + FD = cast(CorrespondingCallOpSpecialization); + } else + FD = LambdaCallOp; } - - // Don't call function pointers which have been cast to some other type. - if (!Info.Ctx.hasSameType(CalleeType->getPointeeType(), FD->getType())) - return Error(E); + } else return Error(E); Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -1263,7 +1263,7 @@ ConvTy, ConvTSI, /*isInline=*/true, /*isExplicit=*/false, - /*isConstexpr=*/false, + /*isConstexpr=*/S.getLangOpts().CPlusPlus1z, 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 @@ -46,5 +46,31 @@ } // end ns test_constexpr_call + +namespace test_conversion_function_for_non_capturing_lambdas { + +namespace ns1 { +auto L = [](int i) { return i; }; +constexpr int (*fpi)(int) = L; +static_assert(fpi(3) == 3); +auto GL = [](auto a) { return a; }; + +constexpr char (*fp2)(char) = GL; +constexpr double (*fp3)(double) = GL; +constexpr const char* (*fp4)(const char*) = GL; +static_assert(fp2('3') == '3'); +static_assert(fp3(3.14) == 3.14); +constexpr const char *Str = "abc"; +static_assert(fp4(Str) == Str); + +auto NCL = [](int i) { static int j; return j; }; //expected-note{{declared here}} +constexpr int (*fp5)(int) = NCL; +constexpr int I = //expected-error{{must be initialized by a constant expression}} + fp5(5); //expected-note{{non-constexpr function}} + +} // end ns1 + +} // end ns test_conversion_function_for_non_capturing_lambdas + #endif // ndef CPP14_AND_EARLIER