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-invalid.cpp =================================================================== --- /dev/null +++ clang/test/CXX/conv/conv.fctptr/template-noexcept-invalid.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s +// RUN: %clang_cc1 -std=c++14 -fsyntax-only %s +// RUN: not %clang_cc1 -std=c++17 -fsyntax-only %s 2>&1 | FileCheck %s +// RUN: not %clang_cc1 -std=c++2a -fsyntax-only %s 2>&1 | FileCheck %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 https://bugs.llvm.org/show_bug.cgi?id=40024 +// Tests the no longer valid function pointer conversions + +struct S { + int f(void) { return 110; } +} s; + +template +int f10(void) { return (s.*a)(); } + +int foo(void) { + return f10<&S::f>(); +} + +// CHECK: error: no matching function for call to 'f10' Index: clang/test/CXX/conv/conv.fctptr/template-noexcept-valid.cpp =================================================================== --- /dev/null +++ clang/test/CXX/conv/conv.fctptr/template-noexcept-valid.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only %s +// RUN: %clang_cc1 -std=c++14 -fsyntax-only %s +// RUN: %clang_cc1 -std=c++17 -fsyntax-only %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only %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 https://bugs.llvm.org/show_bug.cgi?id=40024 +// Tests the still valid function pointer conversions + +struct S { + int f(void) noexcept { return 110; } +} s; + +template +int f10(void) { return (s.*a)(); } + +int foo(void) { + return f10<&S::f>(); +}