Fixed -Wexceptions derived-to-base false positives

...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.)

llvm-svn: 306715
This commit is contained in:
Stephan Bergmann 2017-06-29 17:58:59 +00:00
parent c4bbce724e
commit 743de46043
2 changed files with 41 additions and 1 deletions

View 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);

View File

@ -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 *) {}
}