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:
parent
6f83c75d03
commit
81ef625080
|
@ -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,
|
||||
|
|
|
@ -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>(),
|
||||
|
|
|
@ -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() {}
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue