From b3524deb09dbcaaa5cfec24b4fb447ae906a6d50 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 1 Nov 2016 01:31:23 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@285663 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaOverload.cpp | 29 +++++++++++++++---- lib/Sema/SemaTemplateDeduction.cpp | 9 ++++++ test/SemaCXX/cxx1z-noexcept-function-type.cpp | 14 ++++++++- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 70a4c333f3..cdfb30b30a 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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(); + 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()) + 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; diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index e61197b62c..11d744b72b 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -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(); + 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. diff --git a/test/SemaCXX/cxx1z-noexcept-function-type.cpp b/test/SemaCXX/cxx1z-noexcept-function-type.cpp index 77d073f010..72b28432ef 100644 --- a/test/SemaCXX/cxx1z-noexcept-function-type.cpp +++ b/test/SemaCXX/cxx1z-noexcept-function-type.cpp @@ -17,7 +17,19 @@ template void redecl3() throw(B); typedef int I; template void redecl4(I) noexcept(B); -template void redecl4(I) noexcept(B); +template void redecl4(I) noexcept(B); // expected-note {{failed template argument deduction}} + +void (*init_with_exact_type_a)(int) noexcept = redecl4; +void (*init_with_mismatched_type_a)(int) = redecl4; +auto deduce_auto_from_noexcept_function_ptr_a = redecl4; +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; +void (*init_with_mismatched_type_b)(int) noexcept = redecl4; // expected-error {{does not match required type}} +auto deduce_auto_from_noexcept_function_ptr_b = redecl4; +using DeducedType_b = decltype(deduce_auto_from_noexcept_function_ptr_b); +using DeducedType_b = void (*)(int); namespace DependentDefaultCtorExceptionSpec { template struct T { static const bool value = true; }; -- 2.40.0