diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-06 05:04:56 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-06 05:04:56 +0000 |
commit | 1b26ab1b5287ec6c00e8e506657abe438c90a71b (patch) | |
tree | 0107e12f1ee8eb08535b4042b4e90491a4b4aa3a /lib/Sema | |
parent | 71019a8e1da335af8c2a5d03cb268dd7b19b73a6 (diff) | |
download | clang-1b26ab1b5287ec6c00e8e506657abe438c90a71b.tar.gz |
P1286R2: Remove restriction that the exception specification of a
defaulted special member matches the implicit exception specification.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@360011 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 85 |
2 files changed, 19 insertions, 67 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 8984398eae..7659d7cc00 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -958,7 +958,6 @@ void Sema::ActOnEndOfTranslationUnit() { // incompatible declarations. assert(DelayedOverridingExceptionSpecChecks.empty()); assert(DelayedEquivalentExceptionSpecChecks.empty()); - assert(DelayedDefaultedMemberExceptionSpecs.empty()); // All dllexport classes should have been processed already. assert(DelayedDllExportClasses.empty()); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b8740960fc..8ddc5f12cf 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -6636,6 +6636,8 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // makes such functions always instantiate to constexpr functions. For // functions which cannot be constexpr (for non-constructors in C++11 and for // destructors in C++1y), this is checked elsewhere. + // + // FIXME: This should not apply if the member is deleted. bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM, HasConstParam); if ((getLangOpts().CPlusPlus14 ? !isa<CXXDestructorDecl>(MD) @@ -6647,38 +6649,26 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { HadError = true; } - // and may have an explicit exception-specification only if it is compatible - // with the exception-specification on the implicit declaration. - if (Type->hasExceptionSpec()) { - // Delay the check if this is the first declaration of the special member, - // since we may not have parsed some necessary in-class initializers yet. - if (First) { - // If the exception specification needs to be instantiated, do so now, - // before we clobber it with an EST_Unevaluated specification below. - if (Type->getExceptionSpecType() == EST_Uninstantiated) { - InstantiateExceptionSpec(MD->getBeginLoc(), MD); - Type = MD->getType()->getAs<FunctionProtoType>(); - } - DelayedDefaultedMemberExceptionSpecs.push_back(std::make_pair(MD, Type)); - } else - CheckExplicitlyDefaultedMemberExceptionSpec(MD, Type); - } - - // If a function is explicitly defaulted on its first declaration, if (First) { - // -- it is implicitly considered to be constexpr if the implicit - // definition would be, + // C++2a [dcl.fct.def.default]p3: + // If a function is explicitly defaulted on its first declaration, it is + // implicitly considered to be constexpr if the implicit declaration + // would be. MD->setConstexpr(Constexpr); - // -- it is implicitly considered to have the same exception-specification - // as if it had been implicitly declared, - FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); - EPI.ExceptionSpec.Type = EST_Unevaluated; - EPI.ExceptionSpec.SourceDecl = MD; - MD->setType(Context.getFunctionType(ReturnType, - llvm::makeArrayRef(&ArgType, - ExpectedParams), - EPI)); + if (!Type->hasExceptionSpec()) { + // C++2a [except.spec]p3: + // If a declaration of a function does not have a noexcept-specifier + // [and] is defaulted on its first declaration, [...] the exception + // specification is as specified below + FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo(); + EPI.ExceptionSpec.Type = EST_Unevaluated; + EPI.ExceptionSpec.SourceDecl = MD; + MD->setType(Context.getFunctionType(ReturnType, + llvm::makeArrayRef(&ArgType, + ExpectedParams), + EPI)); + } } if (ShouldDeleteForTypeMismatch || ShouldDeleteSpecialMember(MD, CSM)) { @@ -6711,43 +6701,12 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { MD->setInvalidDecl(); } -/// Check whether the exception specification provided for an -/// explicitly-defaulted special member matches the exception specification -/// that would have been generated for an implicit special member, per -/// C++11 [dcl.fct.def.default]p2. -void Sema::CheckExplicitlyDefaultedMemberExceptionSpec( - CXXMethodDecl *MD, const FunctionProtoType *SpecifiedType) { - // If the exception specification was explicitly specified but hadn't been - // parsed when the method was defaulted, grab it now. - if (SpecifiedType->getExceptionSpecType() == EST_Unparsed) - SpecifiedType = - MD->getTypeSourceInfo()->getType()->castAs<FunctionProtoType>(); - - // Compute the implicit exception specification. - CallingConv CC = Context.getDefaultCallingConvention(/*IsVariadic=*/false, - /*IsCXXMethod=*/true); - FunctionProtoType::ExtProtoInfo EPI(CC); - auto IES = computeImplicitExceptionSpec(*this, MD->getLocation(), MD); - EPI.ExceptionSpec = IES.getExceptionSpec(); - const FunctionProtoType *ImplicitType = cast<FunctionProtoType>( - Context.getFunctionType(Context.VoidTy, None, EPI)); - - // Ensure that it matches. - CheckEquivalentExceptionSpec( - PDiag(diag::err_incorrect_defaulted_exception_spec) - << getSpecialMember(MD), PDiag(), - ImplicitType, SourceLocation(), - SpecifiedType, MD->getLocation()); -} - void Sema::CheckDelayedMemberExceptionSpecs() { decltype(DelayedOverridingExceptionSpecChecks) Overriding; decltype(DelayedEquivalentExceptionSpecChecks) Equivalent; - decltype(DelayedDefaultedMemberExceptionSpecs) Defaulted; std::swap(Overriding, DelayedOverridingExceptionSpecChecks); std::swap(Equivalent, DelayedEquivalentExceptionSpecChecks); - std::swap(Defaulted, DelayedDefaultedMemberExceptionSpecs); // Perform any deferred checking of exception specifications for virtual // destructors. @@ -6758,11 +6717,6 @@ void Sema::CheckDelayedMemberExceptionSpecs() { // special members. for (auto &Check : Equivalent) CheckEquivalentExceptionSpec(Check.second, Check.first); - - // Check that any explicitly-defaulted methods have exception specifications - // compatible with their implicit exception specifications. - for (auto &Spec : Defaulted) - CheckExplicitlyDefaultedMemberExceptionSpec(Spec.first, Spec.second); } namespace { @@ -11398,7 +11352,6 @@ void Sema::ActOnFinishCXXMemberDecls() { if (Record->isInvalidDecl()) { DelayedOverridingExceptionSpecChecks.clear(); DelayedEquivalentExceptionSpecChecks.clear(); - DelayedDefaultedMemberExceptionSpecs.clear(); return; } checkForMultipleExportedDefaultConstructors(*this, Record); |