Author: Zeyi Xu Date: 2026-04-05T22:07:20+08:00 New Revision: 0b7f01ad515d83f1f3144a44a1b0145187eff484
URL: https://github.com/llvm/llvm-project/commit/0b7f01ad515d83f1f3144a44a1b0145187eff484 DIFF: https://github.com/llvm/llvm-project/commit/0b7f01ad515d83f1f3144a44a1b0145187eff484.diff LOG: [clang-tidy] Add frames for bugprone-exception-escape options (#187971) This patch adds frames emitting for `bugprone-exception-escape.TreatFunctionsWithoutSpecificationAsThrowing`. As of AI Usage: Gemini 3 is used for pre-commit reviewing. Closes https://github.com/llvm/llvm-project/issues/184781 Added: Modified: clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-treat-functions-without-specification-as-throwing.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index e4facdad2c7aa..7d23e2d2b5630 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -155,11 +155,19 @@ void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) { return; const utils::ExceptionAnalyzer::CallStack &Stack = ThrowInfo.Stack; - diag(ThrowInfo.Loc, - "frame #0: unhandled exception of type %0 may be thrown in function %1 " - "here", - DiagnosticIDs::Note) - << QualType(ThrowType, 0U) << Stack.back().first; + if (ThrowType) { + diag(ThrowInfo.Loc, + "frame #0: unhandled exception of type %0 may be thrown in function " + "%1 here", + DiagnosticIDs::Note) + << QualType(ThrowType, 0U) << Stack.back().first; + } else { + diag(ThrowInfo.Loc, + "frame #0: an exception of unknown type may be thrown in function %0 " + "here", + DiagnosticIDs::Note) + << Stack.back().first; + } size_t FrameNo = 1; for (auto CurrIt = ++Stack.rbegin(), PrevIt = Stack.rbegin(); diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index 2a54de88dc4d6..9165be3c850d7 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -12,7 +12,6 @@ namespace clang::tidy::utils { void ExceptionAnalyzer::ExceptionInfo::registerException( const Type *ExceptionType, const ThrowInfo &ThrowInfo) { - assert(ExceptionType != nullptr && "Only valid types are accepted"); Behaviour = State::Throwing; ThrownExceptions.insert({ExceptionType, ThrowInfo}); } @@ -432,6 +431,8 @@ ExceptionAnalyzer::ExceptionInfo::filterIgnoredExceptions( // Therefore this slightly hacky implementation is required. for (const auto &ThrownException : ThrownExceptions) { const Type *T = ThrownException.getFirst(); + if (!T) + continue; if (const auto *TD = T->getAsTagDecl()) { if (TD->getDeclName().isIdentifier()) { if ((IgnoreBadAlloc && @@ -484,13 +485,14 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( } } - CallStack.erase(Func); // Optionally treat unannotated functions as potentially throwing if they // are not explicitly non-throwing and no throw was discovered. if (AssumeUnannotatedFunctionsAsThrowing && Result.getBehaviour() == State::NotThrowing && canThrow(Func)) { - Result.registerUnknownException(); + Result.registerException(nullptr, {Func->getLocation(), CallStack}); } + + CallStack.erase(Func); return Result; } @@ -507,8 +509,11 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( } if (AssumeMissingDefinitionsFunctionsAsThrowing && - Result.getBehaviour() == State::Unknown) - Result.registerUnknownException(); + Result.getBehaviour() == State::Unknown) { + CallStack.insert({Func, CallLoc}); + Result.registerException(nullptr, {Func->getLocation(), CallStack}); + CallStack.erase(Func); + } return Result; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-treat-functions-without-specification-as-throwing.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-treat-functions-without-specification-as-throwing.cpp index 6e9aa03323ec7..6f955fa5a012a 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-treat-functions-without-specification-as-throwing.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-treat-functions-without-specification-as-throwing.cpp @@ -15,6 +15,8 @@ void unannotated_no_throw_body() {} void calls_unannotated() noexcept { // CHECK-MESSAGES-ALL: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'calls_unannotated' which should not throw exceptions + // CHECK-MESSAGES-ALL: :[[@LINE-4]]:6: note: frame #0: an exception of unknown type may be thrown in function 'unannotated_no_throw_body' here + // CHECK-MESSAGES-ALL: :[[@LINE+3]]:3: note: frame #1: function 'calls_unannotated' calls function 'unannotated_no_throw_body' here // CHECK-MESSAGES-UNDEFINED-NOT: warning: // CHECK-MESSAGES-NONE-NOT: warning: unannotated_no_throw_body(); @@ -24,7 +26,11 @@ void extern_declared(); void calls_unknown() noexcept { // CHECK-MESSAGES-ALL: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'calls_unknown' which should not throw exceptions - // CHECK-MESSAGES-UNDEFINED: :[[@LINE-2]]:6: warning: an exception may be thrown in function 'calls_unknown' which should not throw exceptions + // CHECK-MESSAGES-ALL: :[[@LINE-4]]:6: note: frame #0: an exception of unknown type may be thrown in function 'extern_declared' here + // CHECK-MESSAGES-ALL: :[[@LINE+5]]:3: note: frame #1: function 'calls_unknown' calls function 'extern_declared' here + // CHECK-MESSAGES-UNDEFINED: :[[@LINE-4]]:6: warning: an exception may be thrown in function 'calls_unknown' which should not throw exceptions + // CHECK-MESSAGES-UNDEFINED: :[[@LINE-7]]:6: note: frame #0: an exception of unknown type may be thrown in function 'extern_declared' here + // CHECK-MESSAGES-UNDEFINED: :[[@LINE+2]]:3: note: frame #1: function 'calls_unknown' calls function 'extern_declared' here // CHECK-MESSAGES-NONE-NOT: warning: extern_declared(); } @@ -54,6 +60,30 @@ void call() noexcept { nothrow_nobody(); } +struct Member { + Member() noexcept {} + Member(const Member &) noexcept {} + Member &operator=(const Member &) noexcept { return *this; } + ~Member() noexcept {} +}; + +struct S { + // CHECK-MESSAGES-ALL: :[[@LINE-1]]:8: warning: an exception may be thrown in function 'S' which should not throw exceptions + // CHECK-MESSAGES-ALL: :[[@LINE-2]]:8: note: frame #0: an exception of unknown type may be thrown in function 'S' here + // CHECK-MESSAGES-ALL: :[[@LINE-3]]:8: warning: an exception may be thrown in function 'operator=' which should not throw exceptions + // CHECK-MESSAGES-ALL: :[[@LINE-4]]:8: note: frame #0: an exception of unknown type may be thrown in function 'operator=' here + // CHECK-MESSAGES-ALL: :[[@LINE-5]]:8: warning: an exception may be thrown in function '~S' which should not throw exceptions + // CHECK-MESSAGES-ALL: :[[@LINE-6]]:8: note: frame #0: an exception of unknown type may be thrown in function '~S' here + // CHECK-MESSAGES-UNDEFINED: :[[@LINE-7]]:8: warning: an exception may be thrown in function 'S' which should not throw exceptions + // CHECK-MESSAGES-UNDEFINED: :[[@LINE-8]]:8: note: frame #0: an exception of unknown type may be thrown in function 'S' here + // CHECK-MESSAGES-UNDEFINED: :[[@LINE-9]]:8: warning: an exception may be thrown in function 'operator=' which should not throw exceptions + // CHECK-MESSAGES-UNDEFINED: :[[@LINE-10]]:8: note: frame #0: an exception of unknown type may be thrown in function 'operator=' here + // CHECK-MESSAGES-UNDEFINED: :[[@LINE-11]]:8: warning: an exception may be thrown in function '~S' which should not throw exceptions + // CHECK-MESSAGES-UNDEFINED: :[[@LINE-12]]:8: note: frame #0: an exception of unknown type may be thrown in function '~S' here + // FIXME: clearly non-throwing functions should not be marked as throwing + Member m; +}; + void explicit_throw() { throw 1; } void calls_explicit_throw() noexcept { // CHECK-MESSAGES-ALL: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'calls_explicit_throw' which should not throw exceptions _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
