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 cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits