https://github.com/Lancern updated https://github.com/llvm/llvm-project/pull/76248
>From c219e38a7953b5bd494554760043053ae3b8ff60 Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Sat, 23 Dec 2023 00:02:08 +0800 Subject: [PATCH 1/2] [clang][Sema] deleted overriding function can have lax except spec --- clang/lib/Sema/SemaExceptionSpec.cpp | 5 +++++ clang/test/CXX/except/except.spec/p5-virtual.cpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index 75730ea888afb4..f8f9c9d491a18e 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -979,6 +979,11 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, if (isa<CXXDestructorDecl>(New) && New->getParent()->isDependentType()) return false; + // CWG1351: if either of the old function or the new function is defined as + // deleted, we don't need this check. + if (Old->isDeleted() || New->isDeleted()) + return false; + // If the old exception specification hasn't been parsed yet, or the new // exception specification can't be computed yet, remember that we need to // perform this check when we get to the end of the outermost diff --git a/clang/test/CXX/except/except.spec/p5-virtual.cpp b/clang/test/CXX/except/except.spec/p5-virtual.cpp index 69daec6ee53347..2cecd6ce51f698 100644 --- a/clang/test/CXX/except/except.spec/p5-virtual.cpp +++ b/clang/test/CXX/except/except.spec/p5-virtual.cpp @@ -45,6 +45,8 @@ struct Base virtual void f15(); virtual void f16(); + virtual void f17() noexcept = delete; + virtual void g1() throw(); // expected-note {{overridden virtual function is here}} virtual void g2() throw(int); // expected-note {{overridden virtual function is here}} virtual void g3() throw(A); // expected-note {{overridden virtual function is here}} @@ -81,6 +83,8 @@ struct Derived : Base virtual void f15() noexcept; virtual void f16() throw(); + virtual void f17() = delete; + virtual void g1() throw(int); // expected-error {{exception specification of overriding function is more lax}} virtual void g2(); // expected-error {{exception specification of overriding function is more lax}} virtual void g3() throw(D); // expected-error {{exception specification of overriding function is more lax}} >From 8a55a5e9c5b746d90a84ab2421873145348379a2 Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Fri, 29 Dec 2023 10:05:44 +0800 Subject: [PATCH 2/2] only check whether New is deleted --- clang/lib/Sema/SemaExceptionSpec.cpp | 97 ++++++++++++++-------------- 1 file changed, 49 insertions(+), 48 deletions(-) diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp index f8f9c9d491a18e..0d815454bdcc68 100644 --- a/clang/lib/Sema/SemaExceptionSpec.cpp +++ b/clang/lib/Sema/SemaExceptionSpec.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Sema/SemaInternal.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Expr.h" @@ -19,14 +18,14 @@ #include "clang/AST/TypeLoc.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" +#include "clang/Sema/SemaInternal.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" #include <optional> namespace clang { -static const FunctionProtoType *GetUnderlyingFunction(QualType T) -{ +static const FunctionProtoType *GetUnderlyingFunction(QualType T) { if (const PointerType *PtrTy = T->getAs<PointerType>()) T = PtrTy->getPointeeType(); else if (const ReferenceType *RefTy = T->getAs<ReferenceType>()) @@ -148,8 +147,7 @@ bool Sema::CheckSpecifiedExceptionType(QualType &T, SourceRange Range) { // C++11 [except.spec]p2: // A type denoted in an exception-specification shall not denote [...] // an rvalue reference type. - Diag(Range.getBegin(), diag::err_rref_in_exception_spec) - << T << Range; + Diag(Range.getBegin(), diag::err_rref_in_exception_spec) << T << Range; return true; } } @@ -237,7 +235,7 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { InstantiateExceptionSpec(Loc, SourceDecl); const FunctionProtoType *Proto = - SourceDecl->getType()->castAs<FunctionProtoType>(); + SourceDecl->getType()->castAs<FunctionProtoType>(); if (Proto->getExceptionSpecType() == clang::EST_Unparsed) { Diag(Loc, diag::err_exception_spec_not_parsed); Proto = nullptr; @@ -245,9 +243,8 @@ Sema::ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT) { return Proto; } -void -Sema::UpdateExceptionSpec(FunctionDecl *FD, - const FunctionProtoType::ExceptionSpecInfo &ESI) { +void Sema::UpdateExceptionSpec( + FunctionDecl *FD, const FunctionProtoType::ExceptionSpecInfo &ESI) { // If we've fully resolved the exception specification, notify listeners. if (!isUnresolvedExceptionSpec(ESI.Type)) if (auto *Listener = getASTMutationListener()) @@ -325,11 +322,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { // Check the types as written: they must match before any exception // specification adjustment is applied. if (!CheckEquivalentExceptionSpecImpl( - *this, PDiag(DiagID), PDiag(diag::note_previous_declaration), - Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), - New->getType()->getAs<FunctionProtoType>(), New->getLocation(), - &MissingExceptionSpecification, &MissingEmptyExceptionSpecification, - /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) { + *this, PDiag(DiagID), PDiag(diag::note_previous_declaration), + Old->getType()->getAs<FunctionProtoType>(), Old->getLocation(), + New->getType()->getAs<FunctionProtoType>(), New->getLocation(), + &MissingExceptionSpecification, &MissingEmptyExceptionSpecification, + /*AllowNoexceptAllMatchWithNoSpec=*/true, IsOperatorNew)) { // C++11 [except.spec]p4 [DR1492]: // If a declaration of a function has an implicit // exception-specification, other declarations of the function shall @@ -337,7 +334,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { if (getLangOpts().CPlusPlus11 && getLangOpts().CXXExceptions && hasImplicitExceptionSpec(Old) != hasImplicitExceptionSpec(New)) { Diag(New->getLocation(), diag::ext_implicit_exception_spec_mismatch) - << hasImplicitExceptionSpec(Old); + << hasImplicitExceptionSpec(Old); if (Old->getLocation().isValid()) Diag(Old->getLocation(), diag::note_previous_declaration); } @@ -455,7 +452,7 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { OS << ")"; break; case EST_NoThrow: - OS <<"__attribute__((nothrow))"; + OS << "__attribute__((nothrow))"; break; case EST_None: case EST_MSAny: @@ -476,12 +473,11 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { } if (FixItLoc.isInvalid()) - Diag(New->getLocation(), DiagID) - << New << OS.str(); + Diag(New->getLocation(), DiagID) << New << OS.str(); else { Diag(New->getLocation(), DiagID) - << New << OS.str() - << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); + << New << OS.str() + << FixItHint::CreateInsertion(FixItLoc, " " + OS.str().str()); } if (Old->getLocation().isValid()) @@ -494,9 +490,10 @@ bool Sema::CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New) { /// exception specifications. Exception specifications are equivalent if /// they allow exactly the same set of exception types. It does not matter how /// that is achieved. See C++ [except.spec]p2. -bool Sema::CheckEquivalentExceptionSpec( - const FunctionProtoType *Old, SourceLocation OldLoc, - const FunctionProtoType *New, SourceLocation NewLoc) { +bool Sema::CheckEquivalentExceptionSpec(const FunctionProtoType *Old, + SourceLocation OldLoc, + const FunctionProtoType *New, + SourceLocation NewLoc) { if (!getLangOpts().CXXExceptions) return false; @@ -504,10 +501,11 @@ bool Sema::CheckEquivalentExceptionSpec( if (getLangOpts().MSVCCompat) DiagID = diag::ext_mismatched_exception_spec; bool Result = CheckEquivalentExceptionSpecImpl( - *this, PDiag(DiagID), PDiag(diag::note_previous_declaration), - Old, OldLoc, New, NewLoc); + *this, PDiag(DiagID), PDiag(diag::note_previous_declaration), Old, OldLoc, + New, NewLoc); - // In Microsoft mode, mismatching exception specifications just cause a warning. + // In Microsoft mode, mismatching exception specifications just cause a + // warning. if (getLangOpts().MSVCCompat) return false; return Result; @@ -573,8 +571,8 @@ static bool CheckEquivalentExceptionSpecImpl( return false; // Any throws-anything specifications are usually compatible. - if (OldCanThrow == CT_Can && OldEST != EST_Dynamic && - NewCanThrow == CT_Can && NewEST != EST_Dynamic) { + if (OldCanThrow == CT_Can && OldEST != EST_Dynamic && NewCanThrow == CT_Can && + NewEST != EST_Dynamic) { // The exception is that the absence of an exception specification only // matches noexcept(false) for functions, as described above. if (!AllowNoexceptAllMatchWithNoSpec && @@ -635,7 +633,7 @@ static bool CheckEquivalentExceptionSpecImpl( // std::bad_alloc, all conditions are met. QualType Exception = *WithExceptions->exception_begin(); if (CXXRecordDecl *ExRecord = Exception->getAsCXXRecordDecl()) { - IdentifierInfo* Name = ExRecord->getIdentifier(); + IdentifierInfo *Name = ExRecord->getIdentifier(); if (Name && Name->getName() == "bad_alloc") { // It's called bad_alloc, but is it in std? if (ExRecord->isInStdNamespace()) { @@ -698,8 +696,8 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) { // FIXME: ObjC pointer types? if (HandlerType->isPointerType() || HandlerType->isMemberPointerType()) { - if (RefTy && (!HandlerType.isConstQualified() || - HandlerType.isVolatileQualified())) + if (RefTy && + (!HandlerType.isConstQualified() || HandlerType.isVolatileQualified())) return false; // -- the handler is of type cv T or const T& where T is a pointer or @@ -729,8 +727,8 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) { Qualifiers EQuals, HQuals; ExceptionType = Context.getUnqualifiedArrayType( ExceptionType->getPointeeType(), EQuals); - HandlerType = Context.getUnqualifiedArrayType( - HandlerType->getPointeeType(), HQuals); + HandlerType = + Context.getUnqualifiedArrayType(HandlerType->getPointeeType(), HQuals); if (!HQuals.compatiblyIncludes(EQuals)) return false; @@ -756,8 +754,10 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) { /*Diagnostic*/ 0, /*ForceCheck*/ true, /*ForceUnprivileged*/ true)) { - case AR_accessible: return true; - case AR_inaccessible: return false; + case AR_accessible: + return true; + case AR_inaccessible: + return false; case AR_dependent: llvm_unreachable("access check dependent for unprivileged context"); case AR_delayed: @@ -885,8 +885,8 @@ CheckSpecForTypesEquivalent(Sema &S, const PartialDiagnostic &DiagID, if (!SFunc) return false; - return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, - SFunc, SourceLoc); + return S.CheckEquivalentExceptionSpec(DiagID, NoteID, TFunc, TargetLoc, SFunc, + SourceLoc); } /// CheckParamExceptionSpec - Check if the parameter and return types of the @@ -901,10 +901,9 @@ bool Sema::CheckParamExceptionSpec( bool SkipSourceFirstParameter, SourceLocation SourceLoc) { auto RetDiag = DiagID; RetDiag << 0; - if (CheckSpecForTypesEquivalent( - *this, RetDiag, PDiag(), - Target->getReturnType(), TargetLoc, Source->getReturnType(), - SourceLoc)) + if (CheckSpecForTypesEquivalent(*this, RetDiag, PDiag(), + Target->getReturnType(), TargetLoc, + Source->getReturnType(), SourceLoc)) return true; // We shouldn't even be testing this unless the arguments are otherwise @@ -979,9 +978,9 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New, if (isa<CXXDestructorDecl>(New) && New->getParent()->isDependentType()) return false; - // CWG1351: if either of the old function or the new function is defined as - // deleted, we don't need this check. - if (Old->isDeleted() || New->isDeleted()) + // CWG1351: if the overriding function is defined as deleted, we don't need + // this check. + if (New->isDeleted()) return false; // If the old exception specification hasn't been parsed yet, or the new @@ -1039,8 +1038,10 @@ CanThrowResult Sema::canCalleeThrow(Sema &S, const Expr *E, const Decl *D, // Could be a call to a pointer-to-member or a plain member access. if (auto *Op = dyn_cast<BinaryOperator>(E)) { assert(Op->getOpcode() == BO_PtrMemD || Op->getOpcode() == BO_PtrMemI); - T = Op->getRHS()->getType() - ->castAs<MemberPointerType>()->getPointeeType(); + T = Op->getRHS() + ->getType() + ->castAs<MemberPointerType>() + ->getPointeeType(); } else { T = cast<MemberExpr>(E)->getMemberDecl()->getType(); } @@ -1111,7 +1112,7 @@ static CanThrowResult canDynamicCastThrow(const CXXDynamicCastExpr *DC) { if (DC->getSubExpr()->isTypeDependent()) return CT_Dependent; - return DC->getCastKind() == clang::CK_Dynamic? CT_Can : CT_Cannot; + return DC->getCastKind() == clang::CK_Dynamic ? CT_Can : CT_Cannot; } static CanThrowResult canTypeidThrow(Sema &S, const CXXTypeidExpr *DC) { @@ -1311,7 +1312,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) { case Expr::CXXAddrspaceCastExprClass: case Expr::CXXReinterpretCastExprClass: case Expr::BuiltinBitCastExprClass: - // FIXME: Properly determine whether a variably-modified type can throw. + // FIXME: Properly determine whether a variably-modified type can throw. if (cast<Expr>(S)->getType()->isVariablyModifiedType()) return CT_Can; return canSubStmtsThrow(*this, S); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits