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:
parent
e322332a09
commit
9095e5bf7e
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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; };
|
||||
|
|
Loading…
Reference in New Issue