isuckatcs created this revision.
isuckatcs added reviewers: njames93, baloghadamsoftware, aaron.ballman,
LegalizeAdulthood.
Herald added subscribers: carlosgalvezp, manas, ASDenysPetrov, dkrupp,
donat.nagy, Szelethus, a.sidorin, rnkovacs, xazax.hun.
Herald added a project: All.
isuckatcs requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.
`ExceptionAnalyzer` only compared exact types in case of pointer,
which is incorrect. An `int *` can be caught by a `const int *` handler,
but `ExceptionAnalyzer` falsely reported it an escaping exception.
For example:
void foo() noexcept {
try {
int a = 1;
throw &a;
} catch (const int *) {
}
}
In function `foo()` the `&a` is caught by the handler, but clang-tidy
reports the following warning:
warning: an exception may be thrown in function 'foo' which should not throw
exceptions [bugprone-exception-escape]
https://reviews.llvm.org/D135495
Files:
clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp
@@ -101,6 +101,84 @@
}
}
+void throw_catch_pointer_c() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_pointer_c' which should not throw exceptions
+ try {
+ int a = 1;
+ throw &a;
+ } catch(const int *) {}
+}
+
+void throw_catch_pointer_v() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_pointer_v' which should not throw exceptions
+ try {
+ int a = 1;
+ throw &a;
+ } catch(volatile int *) {}
+}
+
+void throw_catch_pointer_cv() noexcept {
+ // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_pointer_cv' which should not throw exceptions
+ try {
+ int a = 1;
+ throw &a;
+ } catch(const volatile int *) {}
+}
+
+void throw_c_catch_pointer() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer' which should not throw exceptions
+ try {
+ int a = 1;
+ const int *p = &a;
+ throw p;
+ } catch(int *) {}
+}
+
+void throw_c_catch_pointer_v() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_c_catch_pointer_v' which should not throw exceptions
+ try {
+ int a = 1;
+ const int *p = &a;
+ throw p;
+ } catch(volatile int *) {}
+}
+
+void throw_v_catch_pointer() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer' which should not throw exceptions
+ try {
+ int a = 1;
+ volatile int *p = &a;
+ throw p;
+ } catch(int *) {}
+}
+
+void throw_v_catch_pointer_c() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_v_catch_pointer_c' which should not throw exceptions
+ try {
+ int a = 1;
+ volatile int *p = &a;
+ throw p;
+ } catch(const int *) {}
+}
+
+void throw_cv_catch_pointer_c() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_c' which should not throw exceptions
+ try {
+ int a = 1;
+ const volatile int *p = &a;
+ throw p;
+ } catch(const int *) {}
+}
+
+void throw_cv_catch_pointer_v() noexcept {
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_cv_catch_pointer_v' which should not throw exceptions
+ try {
+ int a = 1;
+ const volatile int *p = &a;
+ throw p;
+ } catch(volatile int *) {}
+}
+
class base {};
class derived: public base {};
Index: clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
===================================================================
--- clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -61,6 +61,24 @@
for (const Type *T : ThrownExceptions) {
if (T == BaseClass || isBaseOf(T, BaseClass))
TypesToDelete.push_back(T);
+ else if (T->isPointerType() && BaseClass->isPointerType()) {
+ auto BPointeeTy = BaseClass->getAs<PointerType>()->getPointeeType();
+ auto TPointeeTy = T->getAs<PointerType>()->getPointeeType();
+
+ auto BCVR = BPointeeTy.getCVRQualifiers();
+ auto TCVR = TPointeeTy.getCVRQualifiers();
+
+ // In case the unqualified types are the same, the exception will be
+ // caught if
+ // 1.) the thrown type doesn't have qualifiers
+ // 2.) the handler has the same qualifiers as the thrown type
+ // 3.) the handle has more qualifiers than the thrown type
+ if (BPointeeTy->getUnqualifiedDesugaredType() ==
+ TPointeeTy->getUnqualifiedDesugaredType() &&
+ (TCVR == 0 || (BCVR ^ TCVR) == 0 || (BCVR & TCVR) > BCVR)) {
+ TypesToDelete.push_back(T);
+ }
+ }
}
for (const Type *T : TypesToDelete)
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits