Permit Exception Spec mismatch with NoThrow on inherited Virtual

As reported here: https://bugs.llvm.org/show_bug.cgi?id=42100

This fairly common pattern ends up being an error in MinGW, so relax it
in all cases to a warning.

llvm-svn: 362434
This commit is contained in:
Erich Keane 2019-06-03 18:36:26 +00:00
parent 6f83c75d03
commit 81ef625080
3 changed files with 35 additions and 3 deletions

View File

@ -1564,6 +1564,7 @@ public:
bool CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
const PartialDiagnostic &NestedDiagID,
const PartialDiagnostic &NoteID,
const PartialDiagnostic &NoThrowDiagID,
const FunctionProtoType *Superset,
SourceLocation SuperLoc,
const FunctionProtoType *Subset,

View File

@ -744,6 +744,7 @@ bool Sema::handlerCanCatch(QualType HandlerType, QualType ExceptionType) {
bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
const PartialDiagnostic &NestedDiagID,
const PartialDiagnostic &NoteID,
const PartialDiagnostic &NoThrowDiagID,
const FunctionProtoType *Superset,
SourceLocation SuperLoc,
const FunctionProtoType *Subset,
@ -790,6 +791,16 @@ bool Sema::CheckExceptionSpecSubset(const PartialDiagnostic &DiagID,
return CheckParamExceptionSpec(NestedDiagID, NoteID, Superset, SuperLoc,
Subset, SubLoc);
// Allow __declspec(nothrow) to be missing on redeclaration as an extension in
// some cases.
if (NoThrowDiagID.getDiagID() != 0 && SubCanThrow == CT_Can &&
SuperCanThrow == CT_Cannot && SuperEST == EST_NoThrow) {
Diag(SubLoc, NoThrowDiagID);
if (NoteID.getDiagID() != 0)
Diag(SuperLoc, NoteID);
return true;
}
// If the subset contains everything or the superset contains nothing, we've
// failed.
if ((SubCanThrow == CT_Can && SubEST != EST_Dynamic) ||
@ -919,9 +930,9 @@ bool Sema::CheckExceptionSpecCompatibility(Expr *From, QualType ToType) {
// void (*q)(void (*) throw(int)) = p;
// }
// ... because it might be instantiated with T=int.
return CheckExceptionSpecSubset(PDiag(DiagID), PDiag(NestedDiagID), PDiag(),
ToFunc, From->getSourceRange().getBegin(),
FromFunc, SourceLocation()) &&
return CheckExceptionSpecSubset(
PDiag(DiagID), PDiag(NestedDiagID), PDiag(), PDiag(), ToFunc,
From->getSourceRange().getBegin(), FromFunc, SourceLocation()) &&
!getLangOpts().CPlusPlus17;
}
@ -953,6 +964,7 @@ bool Sema::CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
return CheckExceptionSpecSubset(PDiag(DiagID),
PDiag(diag::err_deep_exception_specs_differ),
PDiag(diag::note_overridden_virtual_function),
PDiag(diag::ext_override_exception_spec),
Old->getType()->getAs<FunctionProtoType>(),
Old->getLocation(),
New->getType()->getAs<FunctionProtoType>(),

View File

@ -69,3 +69,22 @@ struct S {
__declspec(nothrow) void f4() noexcept(true);
__declspec(nothrow) void f5() noexcept(false);
};
namespace PR42100 {
class Base {
public:
// expected-note@+1{{overridden virtual function is here}}
virtual __declspec(nothrow) void foo() = 0;
// expected-note@+1{{previous declaration is here}}
__declspec(nothrow) void bar();
};
// expected-warning@+1{{'bar' is missing exception specification '__attribute__((nothrow))'}}
void Base::bar() {}
class Sub : public Base {
public:
// expected-warning@+1{{exception specification of overriding function is more lax than base version}}
void foo() {}
};
}