[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
This revision was automatically updated to reflect the committed changes. Closed by commit rGdaac014fec42: [clang-tidy] Check functions called from catch blocks (authored by denizevrenci). Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152330/new/ https://reviews.llvm.org/D152330 Files: clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp === --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -0,0 +1,36 @@ +// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 %s bugprone-exception-escape %t -- \ +// RUN: -- -fexceptions + +void rethrower() { +throw; +} + +void callsRethrower() { +rethrower(); +} + +void callsRethrowerNoexcept() noexcept { +rethrower(); +} + +int throwsAndCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +rethrower(); +} +} + +int throwsAndCallsCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +callsRethrower(); +} +} + +void rethrowerNoexcept() noexcept { +throw; +} Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp === --- clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -36,17 +36,18 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise; template < typename T, bool ThrowInTaskConstructor = false, bool ThrowInPromiseConstructor = false, bool ThrowInInitialSuspend = false, -bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false> +bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false, +bool RethrowInUnhandledException = false> struct Task { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -67,13 +68,13 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Task { +ThrowInUnhandledException, RethrowInUnhandledException> { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -92,7 +93,7 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { Promise() { if constexpr (ThrowInPromiseConstructor) { @@ -130,6 +131,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -138,9 +141,9 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException> { Promise() { if constexpr (ThrowInPromiseConstructor) { throw 1; @@ -170,6 +173,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -266,6 +271,33 @@ co_return a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_return a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_return a / b; +} + +Task +j_ShouldNotDiag(const int a, const int b) { + if (b == 0) +throw b; + + co_return a / b; +} + +Task +j_ShouldDiag(const int a, const int b) noexcept { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions + if (b == 0) +throw b; + + co_return a / b; +} + } // namespace coreturn namespace coyield { @@ -347,6 +379,33 @@ co_yield a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_yield a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_yield a / b; +} + +Task +j_ShouldNotDiag(const int a, const int b) { +
[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
denizevrenci updated this revision to Diff 530296. denizevrenci added a comment. Rebase on main Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152330/new/ https://reviews.llvm.org/D152330 Files: clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp === --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -0,0 +1,36 @@ +// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 %s bugprone-exception-escape %t -- \ +// RUN: -- -fexceptions + +void rethrower() { +throw; +} + +void callsRethrower() { +rethrower(); +} + +void callsRethrowerNoexcept() noexcept { +rethrower(); +} + +int throwsAndCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +rethrower(); +} +} + +int throwsAndCallsCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +callsRethrower(); +} +} + +void rethrowerNoexcept() noexcept { +throw; +} Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp === --- clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -36,17 +36,18 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise; template < typename T, bool ThrowInTaskConstructor = false, bool ThrowInPromiseConstructor = false, bool ThrowInInitialSuspend = false, -bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false> +bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false, +bool RethrowInUnhandledException = false> struct Task { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -67,13 +68,13 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Task { +ThrowInUnhandledException, RethrowInUnhandledException> { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -92,7 +93,7 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { Promise() { if constexpr (ThrowInPromiseConstructor) { @@ -130,6 +131,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -138,9 +141,9 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException> { Promise() { if constexpr (ThrowInPromiseConstructor) { throw 1; @@ -170,6 +173,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -266,6 +271,33 @@ co_return a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_return a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_return a / b; +} + +Task +j_ShouldNotDiag(const int a, const int b) { + if (b == 0) +throw b; + + co_return a / b; +} + +Task +j_ShouldDiag(const int a, const int b) noexcept { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions + if (b == 0) +throw b; + + co_return a / b; +} + } // namespace coreturn namespace coyield { @@ -347,6 +379,33 @@ co_yield a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_yield a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_yield a / b; +} + +Task +j_ShouldNotDiag(const int a, const int b) { + if (b == 0) +throw b; + + co_yield a / b; +} + +Task +j_ShouldDiag(const int a, const
[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
denizevrenci updated this revision to Diff 529140. denizevrenci added a comment. Sort tests out a bit more Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152330/new/ https://reviews.llvm.org/D152330 Files: clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp === --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -0,0 +1,36 @@ +// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 %s bugprone-exception-escape %t -- \ +// RUN: -- -fexceptions + +void rethrower() { +throw; +} + +void callsRethrower() { +rethrower(); +} + +void callsRethrowerNoexcept() noexcept { +rethrower(); +} + +int throwsAndCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +rethrower(); +} +} + +int throwsAndCallsCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +callsRethrower(); +} +} + +void rethrowerNoexcept() noexcept { +throw; +} Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp === --- clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -36,17 +36,18 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise; template < typename T, bool ThrowInTaskConstructor = false, bool ThrowInPromiseConstructor = false, bool ThrowInInitialSuspend = false, -bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false> +bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false, +bool RethrowInUnhandledException = false> struct Task { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -67,13 +68,13 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Task { +ThrowInUnhandledException, RethrowInUnhandledException> { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -92,7 +93,7 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { Promise() { if constexpr (ThrowInPromiseConstructor) { @@ -130,6 +131,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -138,9 +141,9 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException> { Promise() { if constexpr (ThrowInPromiseConstructor) { throw 1; @@ -170,6 +173,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -266,6 +271,33 @@ co_return a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_return a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_return a / b; +} + +Task +j_ShouldNotDiag(const int a, const int b) { + if (b == 0) +throw b; + + co_return a / b; +} + +Task +j_ShouldDiag(const int a, const int b) noexcept { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions + if (b == 0) +throw b; + + co_return a / b; +} + } // namespace coreturn namespace coyield { @@ -347,6 +379,33 @@ co_yield a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_yield a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_yield a / b; +} + +Task +j_ShouldNotDiag(const int a, const int b) { + if (b == 0) +throw b; + + co_yield a / b; +} + +Task +j_ShouldDiag(const
[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
denizevrenci updated this revision to Diff 529137. denizevrenci added a comment. Sort out tests Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152330/new/ https://reviews.llvm.org/D152330 Files: clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp === --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -0,0 +1,36 @@ +// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 %s bugprone-exception-escape %t -- \ +// RUN: -- -fexceptions + +void rethrower() { +throw; +} + +void callsRethrower() { +rethrower(); +} + +void callsRethrowerNoexcept() noexcept { +rethrower(); +} + +int throwsAndCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +rethrower(); +} +} + +int throwsAndCallsCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +callsRethrower(); +} +} + +void rethrowerNoexcept() noexcept { +throw; +} Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp === --- clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -36,17 +36,18 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise; template < typename T, bool ThrowInTaskConstructor = false, bool ThrowInPromiseConstructor = false, bool ThrowInInitialSuspend = false, -bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false> +bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false, +bool RethrowInUnhandledException = false> struct Task { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -67,13 +68,13 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Task { +ThrowInUnhandledException, RethrowInUnhandledException> { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -92,7 +93,7 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { Promise() { if constexpr (ThrowInPromiseConstructor) { @@ -130,6 +131,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -138,9 +141,9 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException> { Promise() { if constexpr (ThrowInPromiseConstructor) { throw 1; @@ -170,6 +173,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -266,6 +271,29 @@ co_return a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_return a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_return a / b; +} + +Task +j_ShouldNotDiag(const int a, const int b) { + throw 1; + co_return a / b; +} + +Task +j_ShouldDiag(const int a, const int b) noexcept { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'j_ShouldDiag' which should not throw exceptions + throw 1; + co_return a / b; +} + } // namespace coreturn namespace coyield { @@ -347,6 +375,29 @@ co_yield a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_yield a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_yield a / b; +} + +Task +j_ShouldNotDiag(const int a, const int b) { + throw 1; + co_yield a / b; +} + +Task +j_ShouldDiag(const int a, const int b) noexcept { + // CHECK-MESSAGES: :[[@LINE-1]]:1:
[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
denizevrenci updated this revision to Diff 529134. denizevrenci added a comment. Rebase on main Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152330/new/ https://reviews.llvm.org/D152330 Files: clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp === --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -0,0 +1,36 @@ +// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 %s bugprone-exception-escape %t -- \ +// RUN: -- -fexceptions + +void rethrower() { +throw; +} + +void callsRethrower() { +rethrower(); +} + +void callsRethrowerNoexcept() noexcept { +rethrower(); +} + +int throwsAndCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +rethrower(); +} +} + +int throwsAndCallsCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +callsRethrower(); +} +} + +void rethrowerNoexcept() noexcept { +throw; +} Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp === --- clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -36,17 +36,18 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise; template < typename T, bool ThrowInTaskConstructor = false, bool ThrowInPromiseConstructor = false, bool ThrowInInitialSuspend = false, -bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false> +bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false, +bool RethrowInUnhandledException = false> struct Task { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -67,13 +68,13 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Task { +ThrowInUnhandledException, RethrowInUnhandledException> { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -92,7 +93,7 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { Promise() { if constexpr (ThrowInPromiseConstructor) { @@ -130,6 +131,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -138,9 +141,9 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException> { Promise() { if constexpr (ThrowInPromiseConstructor) { throw 1; @@ -170,6 +173,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -266,6 +271,23 @@ co_return a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_return a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_return a / b; +} + +Task +i_ShouldDiag(const int a, const int b) noexcept { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'i_ShouldDiag' which should not throw exceptions + throw 1; + co_return a / b; +} + } // namespace coreturn namespace coyield { @@ -347,6 +369,23 @@ co_yield a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_yield a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_yield a / b; +} + +Task +i_ShouldDiag(const int a, const int b) noexcept { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'i_ShouldDiag' which should not throw exceptions + throw 1; + co_yield a / b; +} + } // namespace coyield namespace
[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
ChuanqiXu accepted this revision. ChuanqiXu added a comment. This revision is now accepted and ready to land. LGTM. And please wait for several days for other reviewers. Comment at: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp:132-136 if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } denizevrenci wrote: > ChuanqiXu wrote: > > I don't know clang-tidy a lot. But is these two branches different in > > clang-tidy really? > Yes, rethrows are handled differently than throw expressions with arguments. > You can find the relevant implementation in ExceptionAnalyzer.cpp:[462:475]. OK, sounds good to me. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152330/new/ https://reviews.llvm.org/D152330 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
denizevrenci added inline comments. Comment at: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp:132-136 if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } ChuanqiXu wrote: > I don't know clang-tidy a lot. But is these two branches different in > clang-tidy really? Yes, rethrows are handled differently than throw expressions with arguments. You can find the relevant implementation in ExceptionAnalyzer.cpp:[462:475]. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152330/new/ https://reviews.llvm.org/D152330 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
ChuanqiXu added inline comments. Comment at: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp:132-136 if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } I don't know clang-tidy a lot. But is these two branches different in clang-tidy really? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D152330/new/ https://reviews.llvm.org/D152330 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D152330: [clang-tidy] Check functions called from catch blocks
denizevrenci created this revision. denizevrenci added reviewers: njames93, PiotrZSL, ChuanqiXu. Herald added subscribers: carlosgalvezp, xazax.hun. Herald added a project: All. denizevrenci requested review of this revision. Herald added a project: clang-tools-extra. Herald added a subscriber: cfe-commits. These functions can rethrow a current exception that is caught by the catch block. We can pass the currently caught excections to the function declaration analyzer just like the statement analyzer to handle this case. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D152330 Files: clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp === --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -0,0 +1,36 @@ +// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 %s bugprone-exception-escape %t -- \ +// RUN: -- -fexceptions + +void rethrower() { +throw; +} + +void callsRethrower() { +rethrower(); +} + +void callsRethrowerNoexcept() noexcept { +rethrower(); +} + +int throwsAndCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +rethrower(); +} +} + +int throwsAndCallsCallsRethrower() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions +try { +throw 1; +} catch(...) { +callsRethrower(); +} +} + +void rethrowerNoexcept() noexcept { +throw; +} Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp === --- clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -36,17 +36,18 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise; template < typename T, bool ThrowInTaskConstructor = false, bool ThrowInPromiseConstructor = false, bool ThrowInInitialSuspend = false, -bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false> +bool ThrowInGetReturnObject = false, bool ThrowInUnhandledException = false, +bool RethrowInUnhandledException = false> struct Task { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -67,13 +68,13 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Task { +ThrowInUnhandledException, RethrowInUnhandledException> { using promise_type = Promise; + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException>; explicit Task(promise_type ) { if constexpr (ThrowInTaskConstructor) { @@ -92,7 +93,7 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { Promise() { if constexpr (ThrowInPromiseConstructor) { @@ -130,6 +131,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -138,9 +141,9 @@ template + bool ThrowInUnhandledException, bool RethrowInUnhandledException> struct Promise { + ThrowInGetReturnObject, ThrowInUnhandledException, RethrowInUnhandledException> { Promise() { if constexpr (ThrowInPromiseConstructor) { throw 1; @@ -170,6 +173,8 @@ void unhandled_exception() { if constexpr (ThrowInUnhandledException) { throw 1; +} else if constexpr (RethrowInUnhandledException) { + throw; } } @@ -266,6 +271,23 @@ co_return a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_return a / b; +} + +Task +i_ShouldNotDiagNoexcept(const int a, const int b) noexcept { + co_return a / b; +} + +Task +i_ShouldDiag(const int a, const int b) noexcept { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'i_ShouldDiag' which should not throw exceptions + throw 1; + co_return a / b; +} + } // namespace coreturn namespace coyield { @@ -347,6 +369,23 @@ co_yield a / b; } +Task +i_ShouldNotDiag(const int a, const int b) { + co_yield a / b; +} +