[clang-tools-extra] [clang-tidy] Added bugprone-exception-rethrow check (PR #86448)
via cfe-commits
cfe-commits at lists.llvm.org
Thu May 23 14:01:02 PDT 2024
================
@@ -0,0 +1,83 @@
+.. title:: clang-tidy - bugprone-exception-rethrow
+
+bugprone-exception-rethrow
+==========================
+
+Identifies problematic exception rethrowing, especially with caught exception
+variables or empty throw statements outside catch blocks.
+
+In C++ exception handling, a common pitfall occurs when developers rethrow
+caught exceptions within catch blocks by directly passing the caught exception
+variable to the ``throw`` statement. While this approach can propagate
+exceptions to higher levels of the program, it often leads to code that is less
+clear and more error-prone. Rethrowing caught exceptions with the same exception
+object within catch blocks can obscure the original context of the exception and
+make it challenging to trace program flow. Additionally, this method can
+introduce issues such as exception object slicing and performance overhead due
+to the invocation of the copy constructor.
+
+.. code-block:: c++
+
+ try {
+ // Code that may throw an exception
+ } catch (const std::exception& e) {
+ throw e; // Bad, 'e' is copied
+ }
+
+.. code-block:: c++
+
+ class derived_exception : public std::exception { ... };
+
+ void throwDerived() { throw derived_exception{}; }
+
+ try {
+ throwDerived();
+ } catch (const std::exception& e) {
+ throw e; // Bad, exception slicing occurs when 'derived_exception' is
+ // being rethrown as 'std::exception'
+ }
+
+To prevent these issues, it is advisable to utilize ``throw;`` statements to
+rethrow the original exception object for currently handled exceptions.
+
+.. code-block:: c++
+
+ try {
+ // Code that may throw an exception
+ } catch (const std::exception&) {
+ throw; // Good
+ }
+
+However, when an empty throw statement is used outside a catch block, it
+results in a call to ``std::terminate()``, which abruptly terminates the
+application. This behavior can lead to the abnormal termination of the
+program and is often unintended. Such occurrences may indicate errors or
+oversights in the exception handling logic, and it is essential to avoid empty
+throw statements outside catch blocks to prevent unintended program termination.
+
+.. code-block:: c++
+
+ void foo() {
+ // std::terminate will be called because there is no exception to rethrow
+ throw;
+ }
+
+ int main() {
+ try {
+ foo();
+ } catch(...) {
+ return 1;
+ }
+ return 0;
+ }
----------------
isuckatcs wrote:
Hmm, this got me wondering. What will the checker do in the following case? Will the warning still be reported?
```c++
int main() {
try {
foo(); // bad, will terminate
} catch(...) {
foo(); // good, will rethrow
}
return 0;
}
```
Will it not be reported in this other case?
```c++
int main() {
try {
} catch(...) {
foo(); // good, will rethrow
}
return 0;
}
```
Also I think we should also add this latter example to the docs, to better showcase that it is the execution of the `throw` that matters, not it's usage in source.
https://github.com/llvm/llvm-project/pull/86448
More information about the cfe-commits
mailing list