Test to ensure the function does not have an unresolved or unevaluated exception specification before testing whether the function throws or not. Fixes PR25574.

llvm-svn: 253598
This commit is contained in:
Aaron Ballman 2015-11-19 20:45:35 +00:00
parent 014fb55711
commit f71c9661df
2 changed files with 22 additions and 5 deletions

View File

@ -19,9 +19,12 @@ AST_MATCHER(CXXConstructorDecl, isNoThrowCopyConstructor) {
if (!Node.isCopyConstructor())
return false;
if (const auto *FnTy = Node.getType()->getAs<FunctionProtoType>())
return FnTy->isNothrow(Node.getASTContext());
llvm_unreachable("Copy constructor with no prototype");
const auto *FnTy = Node.getType()->getAs<FunctionProtoType>();
// Assume the best for any unresolved exception specification.
if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType()))
return true;
return FnTy->isNothrow(Node.getASTContext());
}
} // end namespace
@ -36,7 +39,6 @@ void ThrownExceptionTypeCheck::registerMatchers(MatchFinder *Finder) {
isCopyConstructor(), unless(isNoThrowCopyConstructor()))))
.bind("expr"))),
this);
}
void ThrownExceptionTypeCheck::check(const MatchFinder::MatchResult &Result) {

View File

@ -108,5 +108,20 @@ void f() {
throw Allocates(); // match, copy constructor throws
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: thrown exception type is not nothrow copy constructible
throw OptionallyAllocates(); // ok
}
namespace PR25574 {
struct B {
B(const B&) noexcept;
};
struct D : B {
D();
virtual ~D() noexcept;
};
template <typename T>
void f() {
throw D();
}
}