]> granicus.if.org Git - clang/commitdiff
Permit Exception Spec mismatch with NoThrow on inherited Virtual
authorErich Keane <erich.keane@intel.com>
Mon, 3 Jun 2019 18:36:26 +0000 (18:36 +0000)
committerErich Keane <erich.keane@intel.com>
Mon, 3 Jun 2019 18:36:26 +0000 (18:36 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@362434 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaExceptionSpec.cpp
test/SemaCXX/nothrow-vs-exception-specs.cpp

index 7bccaf77c1e9cdb469a16c254ca03f448b4e889f..0c487725bdd42ec66ffed2ff7d8d8f9195d77ce7 100644 (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,
index 8f3ebc29b520782610a353cfc67213fcb835e32b..5274532b0ff89aac22d1a3452dea4b92585896c5 100644 (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>(),
index 78416d8c0b6e031384eeb881be2e069192fe0b33..7a00783b0b78165c35b356b764e0de81cdf8331b 100644 (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() {}
+};
+}