summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h1
-rw-r--r--clang/lib/Sema/SemaExceptionSpec.cpp18
-rw-r--r--clang/test/SemaCXX/nothrow-vs-exception-specs.cpp19
3 files changed, 35 insertions, 3 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 7bccaf77c1e..0c487725bdd 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -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,
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 8f3ebc29b52..5274532b0ff 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -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>(),
diff --git a/clang/test/SemaCXX/nothrow-vs-exception-specs.cpp b/clang/test/SemaCXX/nothrow-vs-exception-specs.cpp
index 78416d8c0b6..7a00783b0b7 100644
--- a/clang/test/SemaCXX/nothrow-vs-exception-specs.cpp
+++ b/clang/test/SemaCXX/nothrow-vs-exception-specs.cpp
@@ -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() {}
+};
+}
OpenPOWER on IntegriCloud