p0012: Teach resolving address of overloaded function with dependent exception

specification to resolve the exception specification as part of the type check,
in C++1z onwards. This is not actually part of P0012 / CWG1330 rules for when
an exception specification is "needed", but is necessary for sanity.

llvm-svn: 285663
This commit is contained in:
Richard Smith 2016-11-01 01:31:23 +00:00
parent e322332a09
commit 9095e5bf7e
3 changed files with 45 additions and 7 deletions

View File

@ -1599,6 +1599,8 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
}
// Check that we've computed the proper type after overload resolution.
// FIXME: FixOverloadedFunctionReference has side-effects; we shouldn't
// be calling it from within an NDEBUG block.
assert(S.Context.hasSameType(
FromType,
S.FixOverloadedFunctionReference(From, AccessPair, Fn)->getType()));
@ -10388,6 +10390,21 @@ QualType Sema::ExtractUnqualifiedFunctionType(QualType PossiblyAFunctionType) {
return Ret;
}
static bool completeFunctionType(Sema &S, FunctionDecl *FD, SourceLocation Loc,
bool Complain = true) {
if (S.getLangOpts().CPlusPlus14 && FD->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(FD, Loc, Complain))
return true;
auto *FPT = FD->getType()->castAs<FunctionProtoType>();
if (S.getLangOpts().CPlusPlus1z &&
isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
!S.ResolveExceptionSpec(Loc, FPT))
return true;
return false;
}
namespace {
// A helper class to help with address of function resolution
// - allows us to avoid passing around all those ugly parameters
@ -10596,9 +10613,8 @@ private:
// If any candidate has a placeholder return type, trigger its deduction
// now.
if (S.getLangOpts().CPlusPlus14 &&
FunDecl->getReturnType()->isUndeducedType() &&
S.DeduceReturnType(FunDecl, SourceExpr->getLocStart(), Complain)) {
if (completeFunctionType(S, FunDecl, SourceExpr->getLocStart(),
Complain)) {
HasComplained |= Complain;
return false;
}
@ -10823,6 +10839,8 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *AddressOfExpr,
else if (NumMatches == 1) {
Fn = Resolver.getMatchingFunctionDecl();
assert(Fn);
if (auto *FPT = Fn->getType()->getAs<FunctionProtoType>())
ResolveExceptionSpec(AddressOfExpr->getExprLoc(), FPT);
FoundResult = *Resolver.getMatchingFunctionAccessPair();
if (Complain) {
if (Resolver.IsStaticMemberFunctionFromBoundPointer())
@ -10982,9 +11000,8 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
if (FoundResult) *FoundResult = I.getPair();
}
if (Matched && getLangOpts().CPlusPlus14 &&
Matched->getReturnType()->isUndeducedType() &&
DeduceReturnType(Matched, ovl->getExprLoc(), Complain))
if (Matched &&
completeFunctionType(*this, Matched, ovl->getExprLoc(), Complain))
return nullptr;
return Matched;

View File

@ -3687,6 +3687,15 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate,
DeduceReturnType(Specialization, Info.getLocation(), false))
return TDK_MiscellaneousDeductionFailure;
// If the function has a dependent exception specification, resolve it now,
// so we can check that the exception specification matches.
auto *SpecializationFPT =
Specialization->getType()->castAs<FunctionProtoType>();
if (getLangOpts().CPlusPlus1z &&
isUnresolvedExceptionSpec(SpecializationFPT->getExceptionSpecType()) &&
!ResolveExceptionSpec(Info.getLocation(), SpecializationFPT))
return TDK_MiscellaneousDeductionFailure;
// If the requested function type does not match the actual type of the
// specialization with respect to arguments of compatible pointer to function
// types, template argument deduction fails.

View File

@ -17,7 +17,19 @@ template<typename A, typename B> void redecl3() throw(B);
typedef int I;
template<bool B> void redecl4(I) noexcept(B);
template<bool B> void redecl4(I) noexcept(B);
template<bool B> void redecl4(I) noexcept(B); // expected-note {{failed template argument deduction}}
void (*init_with_exact_type_a)(int) noexcept = redecl4<true>;
void (*init_with_mismatched_type_a)(int) = redecl4<true>;
auto deduce_auto_from_noexcept_function_ptr_a = redecl4<true>;
using DeducedType_a = decltype(deduce_auto_from_noexcept_function_ptr_a);
using DeducedType_a = void (*)(int) noexcept;
void (*init_with_exact_type_b)(int) = redecl4<false>;
void (*init_with_mismatched_type_b)(int) noexcept = redecl4<false>; // expected-error {{does not match required type}}
auto deduce_auto_from_noexcept_function_ptr_b = redecl4<false>;
using DeducedType_b = decltype(deduce_auto_from_noexcept_function_ptr_b);
using DeducedType_b = void (*)(int);
namespace DependentDefaultCtorExceptionSpec {
template<typename> struct T { static const bool value = true; };