[clang-tidy] Include constructor initializers in bugprone-exception-escape
check
Fixes PR#52435. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D113507
This commit is contained in:
parent
e1b7bd911d
commit
d3b188a2d7
|
@ -119,6 +119,16 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
|
|||
CallStack.insert(Func);
|
||||
ExceptionInfo Result =
|
||||
throwsException(Body, ExceptionInfo::Throwables(), CallStack);
|
||||
|
||||
// For a constructor, we also have to check the initializers.
|
||||
if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(Func)) {
|
||||
for (const CXXCtorInitializer *Init : Ctor->inits()) {
|
||||
ExceptionInfo Excs = throwsException(
|
||||
Init->getInit(), ExceptionInfo::Throwables(), CallStack);
|
||||
Result.merge(Excs);
|
||||
}
|
||||
}
|
||||
|
||||
CallStack.erase(Func);
|
||||
return Result;
|
||||
}
|
||||
|
@ -195,6 +205,14 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException(
|
|||
ExceptionInfo Excs = throwsException(Func, CallStack);
|
||||
Results.merge(Excs);
|
||||
}
|
||||
} else if (const auto *Construct = dyn_cast<CXXConstructExpr>(St)) {
|
||||
ExceptionInfo Excs =
|
||||
throwsException(Construct->getConstructor(), CallStack);
|
||||
Results.merge(Excs);
|
||||
} else if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(St)) {
|
||||
ExceptionInfo Excs =
|
||||
throwsException(DefaultInit->getExpr(), Caught, CallStack);
|
||||
Results.merge(Excs);
|
||||
} else {
|
||||
for (const Stmt *Child : St->children()) {
|
||||
ExceptionInfo Excs = throwsException(Child, Caught, CallStack);
|
||||
|
|
|
@ -288,6 +288,49 @@ int indirectly_recursive(int n) noexcept {
|
|||
return recursion_helper(n);
|
||||
}
|
||||
|
||||
struct super_throws {
|
||||
super_throws() noexcept(false) { throw 42; }
|
||||
};
|
||||
|
||||
struct sub_throws : super_throws {
|
||||
sub_throws() noexcept : super_throws() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions
|
||||
};
|
||||
|
||||
struct super_throws_again {
|
||||
super_throws_again() throw(int);
|
||||
};
|
||||
|
||||
struct sub_throws_again : super_throws_again {
|
||||
sub_throws_again() noexcept : super_throws_again() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws_again' which should not throw exceptions
|
||||
};
|
||||
|
||||
struct init_member_throws {
|
||||
super_throws s;
|
||||
|
||||
init_member_throws() noexcept : s() {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions
|
||||
};
|
||||
|
||||
struct implicit_init_member_throws {
|
||||
super_throws s;
|
||||
|
||||
implicit_init_member_throws() noexcept {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions
|
||||
};
|
||||
|
||||
struct init {
|
||||
explicit init(int, int) noexcept(false) { throw 42; }
|
||||
};
|
||||
|
||||
struct in_class_init_throws {
|
||||
init i{1, 2};
|
||||
|
||||
in_class_init_throws() noexcept {}
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions
|
||||
};
|
||||
|
||||
int main() {
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions
|
||||
throw 1;
|
||||
|
|
Loading…
Reference in a new issue