Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -6991,6 +6991,14 @@ ObjCLifetimeConversion)) RefExpr = ImpCastExprToType(RefExpr.get(), ParamType.getUnqualifiedType(), CK_NoOp); + // Starting with C++17 the noexcept is part of the function signature but + // a noexcept function can be converted to a noexcept(false) function. + QualType ResultTy; + if (getLangOpts().CPlusPlus17 && + IsFunctionConversion(((Expr *)RefExpr.get())->getType(), + ParamType.getUnqualifiedType(), ResultTy)) + RefExpr = ImpCastExprToType(RefExpr.get(), ResultTy, CK_NoOp); + assert(!RefExpr.isInvalid() && Context.hasSameType(((Expr*) RefExpr.get())->getType(), ParamType.getUnqualifiedType())); Index: clang/test/CXX/conv/conv.fctptr/template-noexcept.cpp =================================================================== --- /dev/null +++ clang/test/CXX/conv/conv.fctptr/template-noexcept.cpp @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -verify %s + +// Starting with C++17 the noexcept is part of the function signature but +// a noexcept function can be converted to a noexcept(false) function. +// The tests were added for PR40024. + +#if __cplusplus < 201703L +// expected-no-diagnostics +#endif + +namespace valid_conversion { +struct S { + int f(void) noexcept { return 110; } +} s; + +template +int f10(void) { return (s.*a)(); } + +int foo(void) { + return f10<&S::f>(); +} +} // namespace valid_conversion + +namespace invalid_conversion { +struct S { + int f(void) { return 110; } +} s; + +#if __cplusplus >= 201703L +// expected-note@+3 {{candidate template ignored: invalid explicitly-specified argument for template parameter 'a'}} +#endif +template +int f10(void) { return (s.*a)(); } + +#if __cplusplus >= 201703L +// expected-error@+3 {{no matching function for call to 'f10'}} +#endif +int foo(void) { + return f10<&S::f>(); +} +} // namespace invalid_conversion