]> granicus.if.org Git - clang/commitdiff
Fixed -Wexceptions derived-to-base false positives
authorStephan Bergmann <sbergman@redhat.com>
Thu, 29 Jun 2017 17:58:59 +0000 (17:58 +0000)
committerStephan Bergmann <sbergman@redhat.com>
Thu, 29 Jun 2017 17:58:59 +0000 (17:58 +0000)
...as introduced with recent <https://reviews.llvm.org/D33333> "Emit warning
when throw exception in destruct or dealloc functions which has a (possible
implicit) noexcept specifier".  (The equivalent of the goodReference case hit
when building LibreOffice.)

(These warnings are apparently only emitted when no errors have yet been
encountered, so it didn't work to add the test code to the end of the existing
clang/test/SemaCXX/exceptions.cpp.)

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

lib/Sema/AnalysisBasedWarnings.cpp
test/SemaCXX/exception-warnings.cpp [new file with mode: 0644]

index 934e13e72d056bb83828ed1bcec7e638b4bbf624..fd2d07957c2b8609ba1de1e7e96d65f31c8a1cbb 100644 (file)
@@ -305,10 +305,14 @@ static bool isThrowCaught(const CXXThrowExpr *Throw,
     CaughtType = CaughtType->castAs<ReferenceType>()
                      ->getPointeeType()
                      ->getUnqualifiedDesugaredType();
+  if (ThrowType->isPointerType() && CaughtType->isPointerType()) {
+    ThrowType = ThrowType->getPointeeType()->getUnqualifiedDesugaredType();
+    CaughtType = CaughtType->getPointeeType()->getUnqualifiedDesugaredType();
+  }
   if (CaughtType == ThrowType)
     return true;
   const CXXRecordDecl *CaughtAsRecordType =
-      CaughtType->getPointeeCXXRecordDecl();
+      CaughtType->getAsCXXRecordDecl();
   const CXXRecordDecl *ThrowTypeAsRecordType = ThrowType->getAsCXXRecordDecl();
   if (CaughtAsRecordType && ThrowTypeAsRecordType)
     return ThrowTypeAsRecordType->isDerivedFrom(CaughtAsRecordType);
diff --git a/test/SemaCXX/exception-warnings.cpp b/test/SemaCXX/exception-warnings.cpp
new file mode 100644 (file)
index 0000000..f6c646e
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s
+
+struct B {};
+struct D: B {};
+void goodPlain() throw () {
+  try {
+    throw D();
+  } catch (B) {}
+}
+void goodReference() throw () {
+  try {
+    throw D();
+  } catch (B &) {}
+}
+void goodPointer() throw () {
+  D d;
+  try {
+    throw &d;
+  } catch (B *) {}
+}
+void badPlain() throw () { // expected-note {{non-throwing function declare here}}
+  try {
+    throw B(); // expected-warning {{'badPlain' has a non-throwing exception specification but can still throw, resulting in unexpected program termination}}
+  } catch (D) {}
+}
+void badReference() throw () { // expected-note {{non-throwing function declare here}}
+  try {
+    throw B(); // expected-warning {{'badReference' has a non-throwing exception specification but can still throw, resulting in unexpected program termination}}
+  } catch (D &) {}
+}
+void badPointer() throw () { // expected-note {{non-throwing function declare here}}
+  B b;
+  try {
+    throw &b; // expected-warning {{'badPointer' has a non-throwing exception specification but can still throw, resulting in unexpected program termination}}
+  } catch (D *) {}
+}