From 9fe5ef7b404f5368ba1f1b930c0dde1b5d51414d Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Fri, 4 Apr 2025 15:50:09 +0300 Subject: [PATCH 1/4] [clang-tidy] add stacktrace to exception-escape --- .../bugprone/ExceptionEscapeCheck.cpp | 47 ++++++- .../clang-tidy/utils/ExceptionAnalyzer.cpp | 76 ++++++----- .../clang-tidy/utils/ExceptionAnalyzer.h | 42 ++++-- clang-tools-extra/docs/ReleaseNotes.rst | 4 + .../bugprone/exception-escape-coro.cpp | 124 ++++++++++++++++++ .../bugprone/exception-escape-rethrow.cpp | 4 + .../bugprone/exception-escape-throw.cpp | 9 ++ .../checkers/bugprone/exception-escape.cpp | 107 +++++++++++++++ 8 files changed, 361 insertions(+), 52 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index f008fa4eb9ef7..6574b36129f2c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -78,13 +78,46 @@ void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) { if (!MatchedDecl) return; - if (Tracer.analyze(MatchedDecl).getBehaviour() == - utils::ExceptionAnalyzer::State::Throwing) - // FIXME: We should provide more information about the exact location where - // the exception is thrown, maybe the full path the exception escapes - diag(MatchedDecl->getLocation(), "an exception may be thrown in function " - "%0 which should not throw exceptions") - << MatchedDecl; + const utils::ExceptionAnalyzer::ExceptionInfo Info = + Tracer.analyze(MatchedDecl); + + if (Info.getBehaviour() != utils::ExceptionAnalyzer::State::Throwing) { + return; + } + + diag(MatchedDecl->getLocation(), "an exception may be thrown in function " + "%0 which should not throw exceptions") + << MatchedDecl; + + const utils::ExceptionAnalyzer::ExceptionInfo::ThrowInfo ThrowInfo = + Info.getExceptions().begin()->getSecond(); + + if (ThrowInfo.Loc.isInvalid()) { + return; + } + + // FIXME: We should provide exact position of functions calls, not only call + // stack of thrown exception. + const utils::ExceptionAnalyzer::CallStack &Stack = ThrowInfo.Stack; + diag(Stack.front()->getLocation(), + "example of unhandled exception throw stack, starting from function %0", + DiagnosticIDs::Note) + << Stack.front(); + + size_t FrameNo = 0; + for (const FunctionDecl *CallNode : Stack) { + if (FrameNo != Stack.size() - 1) { + diag(CallNode->getLocation(), "frame #%0: function %1", + DiagnosticIDs::Note) + << FrameNo << CallNode; + } else { + diag(ThrowInfo.Loc, + "frame #%0: function %1 throws unhandled exception here", + DiagnosticIDs::Note) + << FrameNo << CallNode; + } + ++FrameNo; + } } } // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index 6ccc05845220f..c41b6f0a7a76a 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -11,10 +11,10 @@ namespace clang::tidy::utils { void ExceptionAnalyzer::ExceptionInfo::registerException( - const Type *ExceptionType) { + const Type *ExceptionType, const ThrowInfo &ThrowInfo) { assert(ExceptionType != nullptr && "Only valid types are accepted"); Behaviour = State::Throwing; - ThrownExceptions.insert(ExceptionType); + ThrownExceptions.insert({ExceptionType, ThrowInfo}); } void ExceptionAnalyzer::ExceptionInfo::registerExceptions( @@ -356,10 +356,12 @@ static bool canThrow(const FunctionDecl *Func) { }; } -bool ExceptionAnalyzer::ExceptionInfo::filterByCatch( - const Type *HandlerTy, const ASTContext &Context) { +ExceptionAnalyzer::ExceptionInfo::Throwables +ExceptionAnalyzer::ExceptionInfo::filterByCatch(const Type *HandlerTy, + const ASTContext &Context) { llvm::SmallVector TypesToDelete; - for (const Type *ExceptionTy : ThrownExceptions) { + for (const auto &ThrownException : ThrownExceptions) { + const Type *ExceptionTy = ThrownException.getFirst(); CanQualType ExceptionCanTy = ExceptionTy->getCanonicalTypeUnqualified(); CanQualType HandlerCanTy = HandlerTy->getCanonicalTypeUnqualified(); @@ -409,11 +411,18 @@ bool ExceptionAnalyzer::ExceptionInfo::filterByCatch( } } - for (const Type *T : TypesToDelete) - ThrownExceptions.erase(T); + Throwables DeletedExceptions; + + for (const Type *TypeToDelete : TypesToDelete) { + const auto DeleteIt = ThrownExceptions.find(TypeToDelete); + if (DeleteIt != ThrownExceptions.end()) { + DeletedExceptions.insert(*DeleteIt); + ThrownExceptions.erase(DeleteIt); + } + } reevaluateBehaviour(); - return !TypesToDelete.empty(); + return DeletedExceptions; } ExceptionAnalyzer::ExceptionInfo & @@ -422,7 +431,8 @@ ExceptionAnalyzer::ExceptionInfo::filterIgnoredExceptions( llvm::SmallVector TypesToDelete; // Note: Using a 'SmallSet' with 'llvm::remove_if()' is not possible. // Therefore this slightly hacky implementation is required. - for (const Type *T : ThrownExceptions) { + for (const auto &ThrownException : ThrownExceptions) { + const Type *T = ThrownException.getFirst(); if (const auto *TD = T->getAsTagDecl()) { if (TD->getDeclName().isIdentifier()) { if ((IgnoreBadAlloc && @@ -454,10 +464,10 @@ void ExceptionAnalyzer::ExceptionInfo::reevaluateBehaviour() { else Behaviour = State::Throwing; } - -ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( - const FunctionDecl *Func, const ExceptionInfo::Throwables &Caught, - llvm::SmallSet &CallStack) { +ExceptionAnalyzer::ExceptionInfo +ExceptionAnalyzer::throwsException(const FunctionDecl *Func, + const ExceptionInfo::Throwables &Caught, + CallStack &CallStack) { if (!Func || CallStack.contains(Func) || (!CallStack.empty() && !canThrow(Func))) return ExceptionInfo::createNonThrowing(); @@ -475,23 +485,25 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( } } - CallStack.erase(Func); + CallStack.remove(Func); return Result; } auto Result = ExceptionInfo::createUnknown(); if (const auto *FPT = Func->getType()->getAs()) { for (const QualType &Ex : FPT->exceptions()) - Result.registerException(Ex.getTypePtr()); + // Nothing in ThrowInfo because there is no location of 'throw' + Result.registerException(Ex.getTypePtr(), {}); } return Result; } /// Analyzes a single statement on it's throwing behaviour. This is in principle /// possible except some 'Unknown' functions are called. -ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( - const Stmt *St, const ExceptionInfo::Throwables &Caught, - llvm::SmallSet &CallStack) { +ExceptionAnalyzer::ExceptionInfo +ExceptionAnalyzer::throwsException(const Stmt *St, + const ExceptionInfo::Throwables &Caught, + CallStack &CallStack) { auto Results = ExceptionInfo::createNonThrowing(); if (!St) return Results; @@ -505,7 +517,8 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( ->getPointeeType() ->getUnqualifiedDesugaredType(); Results.registerException( - ThrownExpr->getType()->getUnqualifiedDesugaredType()); + ThrownExpr->getType()->getUnqualifiedDesugaredType(), + {Throw->getBeginLoc(), CallStack}); } else // A rethrow of a caught exception happens which makes it possible // to throw all exception that are caught in the 'catch' clause of @@ -520,7 +533,7 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( // Everything is caught through 'catch(...)'. if (!Catch->getExceptionDecl()) { ExceptionInfo Rethrown = throwsException( - Catch->getHandlerBlock(), Uncaught.getExceptionTypes(), CallStack); + Catch->getHandlerBlock(), Uncaught.getExceptions(), CallStack); Results.merge(Rethrown); Uncaught.clear(); } else { @@ -536,12 +549,12 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( // thrown types (because it's sensitive to inheritance) the throwing // situation changes. First of all filter the exception types and // analyze if the baseclass-exception is rethrown. - if (Uncaught.filterByCatch( - CaughtType, Catch->getExceptionDecl()->getASTContext())) { - ExceptionInfo::Throwables CaughtExceptions; - CaughtExceptions.insert(CaughtType); - ExceptionInfo Rethrown = throwsException(Catch->getHandlerBlock(), - CaughtExceptions, CallStack); + const ExceptionInfo::Throwables FilteredExceptions = + Uncaught.filterByCatch(CaughtType, + Catch->getExceptionDecl()->getASTContext()); + if (!FilteredExceptions.empty()) { + ExceptionInfo Rethrown = throwsException( + Catch->getHandlerBlock(), FilteredExceptions, CallStack); Results.merge(Rethrown); } } @@ -569,9 +582,10 @@ ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( } ExceptionInfo Excs = throwsException(Coro->getBody(), Caught, CallStack); Results.merge(throwsException(Coro->getExceptionHandler(), - Excs.getExceptionTypes(), CallStack)); - for (const Type *Throwable : Excs.getExceptionTypes()) { - if (const auto *ThrowableRec = Throwable->getAsCXXRecordDecl()) { + Excs.getExceptions(), CallStack)); + for (const auto &Exception : Excs.getExceptions()) { + const Type *ExcType = Exception.getFirst(); + if (const CXXRecordDecl *ThrowableRec = ExcType->getAsCXXRecordDecl()) { ExceptionInfo DestructorExcs = throwsException(ThrowableRec->getDestructor(), Caught, CallStack); Results.merge(DestructorExcs); @@ -593,7 +607,7 @@ ExceptionAnalyzer::analyzeImpl(const FunctionDecl *Func) { // Check if the function has already been analyzed and reuse that result. const auto CacheEntry = FunctionCache.find(Func); if (CacheEntry == FunctionCache.end()) { - llvm::SmallSet CallStack; + CallStack CallStack; ExceptionList = throwsException(Func, ExceptionInfo::Throwables(), CallStack); @@ -610,7 +624,7 @@ ExceptionAnalyzer::analyzeImpl(const FunctionDecl *Func) { ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::analyzeImpl(const Stmt *Stmt) { - llvm::SmallSet CallStack; + CallStack CallStack; return throwsException(Stmt, ExceptionInfo::Throwables(), CallStack); } diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h index 6c2d693d64b50..0fea44fc8a622 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h @@ -12,6 +12,7 @@ #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSet.h" namespace clang::tidy::utils { @@ -28,6 +29,12 @@ class ExceptionAnalyzer { ///< definition. }; + /// We use a SetVector to preserve the order of the functions in the call + /// stack as well as have fast lookup. + using CallStack = llvm::SetVector, + llvm::DenseSet, 32>; + /// Bundle the gathered information about an entity like a function regarding /// it's exception behaviour. The 'NonThrowing'-state can be considered as the /// neutral element in terms of information propagation. @@ -37,7 +44,15 @@ class ExceptionAnalyzer { /// exception at runtime. class ExceptionInfo { public: - using Throwables = llvm::SmallSet; + /// Holds information about where an exception is thrown. + /// First element in the call stack is analyzed function. + struct ThrowInfo { + SourceLocation Loc; + CallStack Stack; + }; + + using Throwables = llvm::SmallDenseMap; + static ExceptionInfo createUnknown() { return {State::Unknown}; } static ExceptionInfo createNonThrowing() { return {State::Throwing}; } @@ -56,7 +71,8 @@ class ExceptionAnalyzer { /// Register a single exception type as recognized potential exception to be /// thrown. - void registerException(const Type *ExceptionType); + void registerException(const Type *ExceptionType, + const ThrowInfo &ThrowInfo); /// Registers a `SmallVector` of exception types as recognized potential /// exceptions to be thrown. @@ -73,8 +89,8 @@ class ExceptionAnalyzer { /// This method is useful in case 'catch' clauses are analyzed as it is /// possible to catch multiple exception types by one 'catch' if they /// are a subclass of the 'catch'ed exception type. - /// Returns 'true' if some exceptions were filtered, otherwise 'false'. - bool filterByCatch(const Type *HandlerTy, const ASTContext &Context); + /// Returns filtered exceptions. + Throwables filterByCatch(const Type *HandlerTy, const ASTContext &Context); /// Filter the set of thrown exception type against a set of ignored /// types that shall not be considered in the exception analysis. @@ -87,9 +103,9 @@ class ExceptionAnalyzer { /// neutral. void clear(); - /// References the set of known exception types that can escape from the + /// References the set of known exceptions that can escape from the /// corresponding entity. - const Throwables &getExceptionTypes() const { return ThrownExceptions; } + const Throwables &getExceptions() const { return ThrownExceptions; } /// Signal if the there is any 'Unknown' element within the scope of /// the related entity. This might be relevant if the entity is 'Throwing' @@ -126,14 +142,12 @@ class ExceptionAnalyzer { ExceptionInfo analyze(const Stmt *Stmt); private: - ExceptionInfo - throwsException(const FunctionDecl *Func, - const ExceptionInfo::Throwables &Caught, - llvm::SmallSet &CallStack); - ExceptionInfo - throwsException(const Stmt *St, const ExceptionInfo::Throwables &Caught, - llvm::SmallSet &CallStack); - + ExceptionInfo throwsException(const FunctionDecl *Func, + const ExceptionInfo::Throwables &Caught, + CallStack &CallStack); + ExceptionInfo throwsException(const Stmt *St, + const ExceptionInfo::Throwables &Caught, + CallStack &CallStack); ExceptionInfo analyzeImpl(const FunctionDecl *Func); ExceptionInfo analyzeImpl(const Stmt *Stmt); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 36a41b4bdf42d..afaa04e4083c7 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -187,6 +187,10 @@ Changes in existing checks false positives on deleted constructors that cannot be used to construct objects, even if they have public or protected access. +- Improved :doc:`bugprone-exception-escape + ` check to print stack trace + of a potentially escaped exception. + - Added an option to :doc:`bugprone-multi-level-implicit-pointer-conversion ` to choose whether to enable the check in C code or not. diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp index aff13d19fd209..829ec30353b94 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -221,6 +221,9 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_return a / b; } +// CHECK-MESSAGES: :[[@LINE-7]]:11: note: example of unhandled exception throw stack, starting from function 'c_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #0: function 'c_ShouldDiag' +// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here Task d_ShouldNotDiag(const int a, const int b) { co_return a / b; @@ -230,6 +233,10 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_return a / b; } +// CHECK-MESSAGES: :[[@LINE-4]]:17: note: example of unhandled exception throw stack, starting from function 'd_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:17: note: frame #0: function 'd_ShouldDiag' +// CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' +// CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here Task e_ShouldNotDiag(const int a, const int b) { co_return a / b; @@ -239,6 +246,9 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_return a / b; } +// CHECK-MESSAGES: :[[@LINE-4]]:24: note: example of unhandled exception throw stack, starting from function 'e_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #0: function 'e_ShouldDiag' +// CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here Task f_ShouldNotDiag(const int a, const int b) { co_return a / b; @@ -248,6 +258,9 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_return a / b; } +// CHECK-MESSAGES: :[[@LINE-4]]:31: note: example of unhandled exception throw stack, starting from function 'f_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #0: function 'f_ShouldDiag' +// CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here Task g_ShouldNotDiag(const int a, const int b) { co_return a / b; @@ -258,6 +271,9 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_return a / b; } +// CHECK-MESSAGES: :[[@LINE-5]]:38: note: example of unhandled exception throw stack, starting from function 'g_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #0: function 'g_ShouldDiag' +// CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here Task h_ShouldNotDiag(const int a, const int b) { @@ -269,6 +285,9 @@ Task h_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_return a / b; } +// CHECK-MESSAGES: :[[@LINE-5]]:45: note: example of unhandled exception throw stack, starting from function 'h_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #0: function 'h_ShouldDiag' +// CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here Task i_ShouldNotDiag(const int a, const int b) { @@ -296,6 +315,8 @@ j_ShouldDiag(const int a, const int b) noexcept { co_return a / b; } +// CHECK-MESSAGES: :[[@LINE-7]]:1: note: example of unhandled exception throw stack, starting from function 'j_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here } // namespace coreturn @@ -329,6 +350,9 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_yield a / b; } +// CHECK-MESSAGES: :[[@LINE-7]]:11: note: example of unhandled exception throw stack, starting from function 'c_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #0: function 'c_ShouldDiag' +// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here Task d_ShouldNotDiag(const int a, const int b) { co_yield a / b; @@ -338,6 +362,10 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_yield a / b; } +// CHECK-MESSAGES: :[[@LINE-4]]:17: note: example of unhandled exception throw stack, starting from function 'd_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:17: note: frame #0: function 'd_ShouldDiag' +// CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' +// CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here Task e_ShouldNotDiag(const int a, const int b) { co_yield a / b; @@ -347,6 +375,9 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_yield a / b; } +// CHECK-MESSAGES: :[[@LINE-4]]:24: note: example of unhandled exception throw stack, starting from function 'e_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #0: function 'e_ShouldDiag' +// CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here Task f_ShouldNotDiag(const int a, const int b) { co_yield a / b; @@ -356,6 +387,9 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_yield a / b; } +// CHECK-MESSAGES: :[[@LINE-4]]:31: note: example of unhandled exception throw stack, starting from function 'f_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #0: function 'f_ShouldDiag' +// CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here Task g_ShouldNotDiag(const int a, const int b) { co_yield a / b; @@ -366,6 +400,9 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_yield a / b; } +// CHECK-MESSAGES: :[[@LINE-5]]:38: note: example of unhandled exception throw stack, starting from function 'g_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #0: function 'g_ShouldDiag' +// CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here Task h_ShouldNotDiag(const int a, const int b) { @@ -377,6 +414,9 @@ Task h_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_yield a / b; } +// CHECK-MESSAGES: :[[@LINE-5]]:45: note: example of unhandled exception throw stack, starting from function 'h_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #0: function 'h_ShouldDiag' +// CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here Task i_ShouldNotDiag(const int a, const int b) { @@ -404,6 +444,8 @@ j_ShouldDiag(const int a, const int b) noexcept { co_yield a / b; } +// CHECK-MESSAGES: :[[@LINE-7]]:1: note: example of unhandled exception throw stack, starting from function 'j_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here } // namespace coyield @@ -437,6 +479,9 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_await returnOne(); } +// CHECK-MESSAGES: :[[@LINE-7]]:12: note: example of unhandled exception throw stack, starting from function 'c_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #0: function 'c_ShouldDiag' +// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here Task d_ShouldNotDiag(const int a, const int b) { co_await returnOne(); @@ -446,6 +491,10 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_await returnOne(); } +// CHECK-MESSAGES: :[[@LINE-4]]:18: note: example of unhandled exception throw stack, starting from function 'd_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:18: note: frame #0: function 'd_ShouldDiag' +// CHECK-MESSAGES: :153:8: note: frame #1: function 'get_return_object' +// CHECK-MESSAGES: :81:7: note: frame #2: function 'Task' throws unhandled exception here Task e_ShouldNotDiag(const int a, const int b) { co_await returnOne(); @@ -455,6 +504,9 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_await returnOne(); } +// CHECK-MESSAGES: :[[@LINE-4]]:25: note: example of unhandled exception throw stack, starting from function 'e_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:25: note: frame #0: function 'e_ShouldDiag' +// CHECK-MESSAGES: :149:7: note: frame #1: function 'Promise' throws unhandled exception here Task f_ShouldNotDiag(const int a, const int b) { co_await returnOne(); @@ -464,6 +516,9 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_await returnOne(); } +// CHECK-MESSAGES: :[[@LINE-4]]:32: note: example of unhandled exception throw stack, starting from function 'f_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:32: note: frame #0: function 'f_ShouldDiag' +// CHECK-MESSAGES: :163:7: note: frame #1: function 'initial_suspend' throws unhandled exception here Task g_ShouldNotDiag(const int a, const int b) { @@ -475,6 +530,9 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_await returnOne(); } +// CHECK-MESSAGES: :[[@LINE-5]]:39: note: example of unhandled exception throw stack, starting from function 'g_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-6]]:39: note: frame #0: function 'g_ShouldDiag' +// CHECK-MESSAGES: :155:7: note: frame #1: function 'get_return_object' throws unhandled exception here Task h_ShouldNotDiag(const int a, const int b) { @@ -486,6 +544,9 @@ h_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_await returnOne(); } +// CHECK-MESSAGES: :[[@LINE-4]]:1: note: example of unhandled exception throw stack, starting from function 'h_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:1: note: frame #0: function 'h_ShouldDiag' +// CHECK-MESSAGES: :175:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here Task i_ShouldNotDiag(const int a, const int b) { @@ -511,6 +572,8 @@ j_ShouldDiag(const int a, const int b) noexcept { if (b == 0) throw b; } +// CHECK-MESSAGES: :[[@LINE-6]]:1: note: example of unhandled exception throw stack, starting from function 'j_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here } // namespace coawait @@ -549,6 +612,9 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_return a / b; }; +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { co_return a / b; @@ -559,6 +625,10 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' +// CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here const auto e_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -570,6 +640,9 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here const auto f_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -581,6 +654,9 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here const auto g_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -593,6 +669,9 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here const auto h_ShouldNotDiag = [](const int a, @@ -606,6 +685,9 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here const auto i_ShouldNotDiag = [](const int a, @@ -637,6 +719,8 @@ const auto j_ShouldDiag = co_return a / b; }; +// CHECK-MESSAGES: :[[@LINE-8]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' throws unhandled exception here } // namespace coreturn @@ -671,6 +755,9 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_yield a / b; }; +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { co_yield a / b; @@ -681,6 +768,9 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' const auto e_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -692,6 +782,9 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here const auto f_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -703,6 +796,9 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here const auto g_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -715,6 +811,9 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here const auto h_ShouldNotDiag = [](const int a, @@ -728,6 +827,9 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here const auto i_ShouldNotDiag = [](const int a, @@ -759,6 +861,8 @@ const auto j_ShouldDiag = co_yield a / b; }; +// CHECK-MESSAGES: :[[@LINE-8]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' throws unhandled exception here } // namespace coyield @@ -793,6 +897,9 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_await returnOne(); }; +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { co_await returnOne(); @@ -803,6 +910,9 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :153:8: note: frame #1: function 'get_return_object' const auto e_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -814,6 +924,9 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :149:7: note: frame #1: function 'Promise' throws unhandled exception here const auto f_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -825,6 +938,9 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :163:7: note: frame #1: function 'initial_suspend' throws unhandled exception here const auto g_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -837,6 +953,9 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :155:7: note: frame #1: function 'get_return_object' throws unhandled exception here const auto h_ShouldNotDiag = [](const int a, @@ -850,6 +969,9 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' +// CHECK-MESSAGES: :175:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here const auto i_ShouldNotDiag = [](const int a, @@ -879,6 +1001,8 @@ const auto j_ShouldDiag = if (b == 0) throw b; }; +// CHECK-MESSAGES: :[[@LINE-7]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: function 'operator()' throws unhandled exception here } // namespace coawait diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp index 6f961a247b9d2..a58717fc7104b 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -22,6 +22,8 @@ int throwsAndCallsRethrower() noexcept { } return 1; } +// CHECK-MESSAGES: :[[@LINE-9]]:5: note: example of unhandled exception throw stack, starting from function 'throwsAndCallsRethrower' +// CHECK-MESSAGES: :[[@LINE-7]]:9: note: frame #0: function 'throwsAndCallsRethrower' throws unhandled exception here int throwsAndCallsCallsRethrower() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions @@ -32,6 +34,8 @@ int throwsAndCallsCallsRethrower() noexcept { } return 1; } +// CHECK-MESSAGES: :[[@LINE-9]]:5: note: example of unhandled exception throw stack, starting from function 'throwsAndCallsCallsRethrower' +// CHECK-MESSAGES: :[[@LINE-7]]:9: note: frame #0: function 'throwsAndCallsCallsRethrower' throws unhandled exception here void rethrowerNoexcept() noexcept { throw; diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp index 4a0113b8be3b3..1dd569de94af2 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp @@ -4,6 +4,8 @@ void throwing_throw_nothing() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions throw 1; } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'throwing_throw_nothing' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'throwing_throw_nothing' throws unhandled exception here void explicit_int_thrower() throw(int); @@ -15,11 +17,15 @@ void indirect_implicit() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions implicit_int_thrower(); } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'indirect_implicit' +// CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_implicit' +// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #1: function 'implicit_int_thrower' throws unhandled exception here void indirect_explicit() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions explicit_int_thrower(); } +// FIXME: no diagnostics because 'explicit_int_thrower' has no explicit 'throw' expression struct super_throws { super_throws() throw(int) { throw 42; } @@ -29,3 +35,6 @@ struct sub_throws : super_throws { sub_throws() throw() : super_throws() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions }; +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'sub_throws' +// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'sub_throws' +// CHECK-MESSAGES: :[[@LINE-9]]:31: note: frame #1: function 'super_throws' throws unhandled exception here diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp index aae957dd7e090..8f9178eb64852 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp @@ -12,6 +12,8 @@ struct throwing_destructor { throw 1; } }; +// CHECK-MESSAGES: :[[@LINE-5]]:3: note: example of unhandled exception throw stack, starting from function '~throwing_destructor' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function '~throwing_destructor' throws unhandled exception here struct throwing_move_constructor { throwing_move_constructor(throwing_move_constructor&&) { @@ -19,6 +21,8 @@ struct throwing_move_constructor { throw 1; } }; +// CHECK-MESSAGES: :[[@LINE-5]]:3: note: example of unhandled exception throw stack, starting from function 'throwing_move_constructor' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throwing_move_constructor' throws unhandled exception here struct throwing_move_assignment { throwing_move_assignment& operator=(throwing_move_assignment&&) { @@ -26,11 +30,15 @@ struct throwing_move_assignment { throw 1; } }; +// CHECK-MESSAGES: :[[@LINE-5]]:29: note: example of unhandled exception throw stack, starting from function 'operator=' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'operator=' throws unhandled exception here void throwing_noexcept() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions throw 1; } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'throwing_noexcept' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'throwing_noexcept' throws unhandled exception here void throw_and_catch() noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions @@ -48,6 +56,8 @@ void throw_and_catch_some(int n) noexcept { } catch(int &) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_and_catch_some' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_and_catch_some' throws unhandled exception here void throw_and_catch_each(int n) noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions @@ -76,6 +86,8 @@ void throw_and_rethrow() noexcept { throw; } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_and_rethrow' +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'throw_and_rethrow' throws unhandled exception here void throw_catch_throw() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions @@ -85,6 +97,8 @@ void throw_catch_throw() noexcept { throw 2; } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_catch_throw' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_catch_throw' throws unhandled exception here void throw_catch_rethrow_the_rest(int n) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions @@ -96,6 +110,8 @@ void throw_catch_rethrow_the_rest(int n) noexcept { throw; } } +// CHECK-MESSAGES: :[[@LINE-10]]:6: note: example of unhandled exception throw stack, starting from function 'throw_catch_rethrow_the_rest' +// CHECK-MESSAGES: :[[@LINE-7]]:5: note: frame #0: function 'throw_catch_rethrow_the_rest' throws unhandled exception here void throw_catch_pointer_c() noexcept { try { @@ -126,6 +142,8 @@ void throw_catch_multi_ptr_1() noexcept { } catch (const char **) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_catch_multi_ptr_1' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_catch_multi_ptr_1' throws unhandled exception here void throw_catch_multi_ptr_2() noexcept { try { @@ -171,6 +189,8 @@ void throw_c_catch_pointer() noexcept { throw p; } catch(int *) {} } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_c_catch_pointer' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_c_catch_pointer' throws unhandled exception here 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 @@ -180,6 +200,8 @@ void throw_c_catch_pointer_v() noexcept { throw p; } catch(volatile int *) {} } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_c_catch_pointer_v' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_c_catch_pointer_v' throws unhandled exception here 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 @@ -189,6 +211,8 @@ void throw_v_catch_pointer() noexcept { throw p; } catch(int *) {} } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_v_catch_pointer' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_v_catch_pointer' throws unhandled exception here 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 @@ -198,6 +222,8 @@ void throw_v_catch_pointer_c() noexcept { throw p; } catch(const int *) {} } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_v_catch_pointer_c' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_v_catch_pointer_c' throws unhandled exception here 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 @@ -207,6 +233,8 @@ void throw_cv_catch_pointer_c() noexcept { throw p; } catch(const int *) {} } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_cv_catch_pointer_c' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_cv_catch_pointer_c' throws unhandled exception here 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 @@ -216,6 +244,8 @@ void throw_cv_catch_pointer_v() noexcept { throw p; } catch(volatile int *) {} } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_cv_catch_pointer_v' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_cv_catch_pointer_v' throws unhandled exception here class base {}; class derived: public base {}; @@ -263,6 +293,8 @@ void throw_derived_catch_base_ptr() noexcept { } catch(base *) { } } +// CHECK-MESSAGES: :[[@LINE-9]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_ptr' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ptr' throws unhandled exception here class A {}; class B : A {}; @@ -286,6 +318,8 @@ void throw_derived_catch_base_private() noexcept { } catch(A) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_private' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_private' throws unhandled exception here void throw_derived_catch_base_private_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private_ptr' which should not throw exceptions @@ -295,6 +329,8 @@ void throw_derived_catch_base_private_ptr() noexcept { } catch(A *) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_private_ptr' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_private_ptr' throws unhandled exception here void throw_derived_catch_base_protected() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected' which should not throw exceptions @@ -304,6 +340,8 @@ void throw_derived_catch_base_protected() noexcept { } catch(A) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_protected' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_protected' throws unhandled exception here void throw_derived_catch_base_protected_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected_ptr' which should not throw exceptions @@ -313,6 +351,8 @@ void throw_derived_catch_base_protected_ptr() noexcept { } catch(A *) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_protected_ptr' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_protected_ptr' throws unhandled exception here void throw_derived_catch_base_ambiguous() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous' which should not throw exceptions @@ -322,6 +362,8 @@ void throw_derived_catch_base_ambiguous() noexcept { } catch(A) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_ambiguous' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ambiguous' throws unhandled exception here void throw_derived_catch_base_ambiguous_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' which should not throw exceptions @@ -331,6 +373,8 @@ void throw_derived_catch_base_ambiguous_ptr() noexcept { } catch(A) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_ambiguous_ptr' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ambiguous_ptr' throws unhandled exception here void throw_alias_catch_original() noexcept { using alias = int; @@ -352,6 +396,8 @@ void throw_alias_catch_original_warn() noexcept { } catch (int) { } } +// CHECK-MESSAGES: :[[@LINE-10]]:6: note: example of unhandled exception throw stack, starting from function 'throw_alias_catch_original_warn' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_alias_catch_original_warn' throws unhandled exception here void throw_original_catch_alias() noexcept { using alias = char; @@ -373,6 +419,8 @@ void throw_original_catch_alias_warn() noexcept { } catch (volatile const alias *const *) { } } +// CHECK-MESSAGES: :[[@LINE-10]]:6: note: example of unhandled exception throw stack, starting from function 'throw_original_catch_alias_warn' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_original_catch_alias_warn' throws unhandled exception here void throw_original_catch_alias_2() noexcept { using alias = const char *const; @@ -433,6 +481,8 @@ void throw_basefn_catch_derivedfn() noexcept { } catch(void(derivedMember::*)()) { } } +// CHECK-MESSAGES: :[[@LINE-7]]:6: note: example of unhandled exception throw stack, starting from function 'throw_basefn_catch_derivedfn' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basefn_catch_derivedfn' throws unhandled exception here void throw_basefn_catch_basefn() noexcept { try { @@ -449,6 +499,8 @@ void throw_basem_catch_basem_throw() noexcept { } catch(const int* baseMember::* const *) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_basem_catch_basem_throw' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basem_catch_basem_throw' throws unhandled exception here void throw_basem_catch_basem() noexcept { try { @@ -466,6 +518,8 @@ void throw_basem_catch_derivedm() noexcept { } catch(const int* const derivedMember::* const *) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_basem_catch_derivedm' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basem_catch_derivedm' throws unhandled exception here void throw_derivedm_catch_basem() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derivedm_catch_basem' which should not throw exceptions @@ -475,6 +529,8 @@ void throw_derivedm_catch_basem() noexcept { } catch(const int* const baseMember::* const *) { } } +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derivedm_catch_basem' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derivedm_catch_basem' throws unhandled exception here void throw_original_catch_alias_2_warn() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_2_warn' which should not throw exceptions @@ -486,6 +542,8 @@ void throw_original_catch_alias_2_warn() noexcept { } catch (volatile alias *) { } } +// CHECK-MESSAGES: :[[@LINE-10]]:6: note: example of unhandled exception throw stack, starting from function 'throw_original_catch_alias_2_warn' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_original_catch_alias_2_warn' throws unhandled exception here void try_nested_try(int n) noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions @@ -510,6 +568,8 @@ void bad_try_nested_try(int n) noexcept { } catch(double &) { } } +// CHECK-MESSAGES: :[[@LINE-11]]:6: note: example of unhandled exception throw stack, starting from function 'bad_try_nested_try' +// CHECK-MESSAGES: :[[@LINE-9]]:12: note: frame #0: function 'bad_try_nested_try' throws unhandled exception here void try_nested_catch() noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions @@ -547,6 +607,8 @@ void bad_catch_nested_try() noexcept { } catch(double &) { } } +// CHECK-MESSAGES: :[[@LINE-12]]:6: note: example of unhandled exception throw stack, starting from function 'bad_catch_nested_try' +// CHECK-MESSAGES: :[[@LINE-7]]:7: note: frame #0: function 'bad_catch_nested_try' throws unhandled exception here void implicit_int_thrower() { throw 1; @@ -560,11 +622,17 @@ void indirect_implicit() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions implicit_int_thrower(); } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'indirect_implicit' +// CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_implicit' +// CHECK-MESSAGES: :[[@LINE-13]]:3: note: frame #1: function 'implicit_int_thrower' throws unhandled exception here void indirect_explicit() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions explicit_int_thrower(); } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'indirect_explicit' +// CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_explicit' +// CHECK-MESSAGES: :[[@LINE-17]]:3: note: frame #1: function 'explicit_int_thrower' throws unhandled exception here void indirect_catch() noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions @@ -585,16 +653,22 @@ void swap(int&, int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions throw 1; } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'swap' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'swap' throws unhandled exception here void iter_swap(int&, int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions throw 1; } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'iter_swap' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'iter_swap' throws unhandled exception here void iter_move(int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' which should not throw exceptions throw 1; } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'iter_move' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'iter_move' throws unhandled exception here namespace std { class bad_alloc {}; @@ -613,11 +687,16 @@ void enabled1() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions throw 1; } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'enabled1' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'enabled1' throws unhandled exception here void enabled2() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions enabled1(); } +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'enabled2' +// CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'enabled2' +// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #1: function 'enabled1' throws unhandled exception here void enabled3() { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions @@ -649,6 +728,8 @@ void this_counts(int n) noexcept { if (n) throw 1; throw ignored1(); } +// CHECK-MESSAGES: :[[@LINE-5]]:6: note: example of unhandled exception throw stack, starting from function 'this_counts' +// CHECK-MESSAGES: :[[@LINE-4]]:10: note: frame #0: function 'this_counts' throws unhandled exception here void thrower(int n) { throw n; @@ -660,6 +741,9 @@ int directly_recursive(int n) noexcept { thrower(n); return directly_recursive(n); } +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: example of unhandled exception throw stack, starting from function 'directly_recursive' +// CHECK-MESSAGES: :[[@LINE-7]]:5: note: frame #0: function 'directly_recursive' +// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #1: function 'thrower' throws unhandled exception here int indirectly_recursive(int n) noexcept; @@ -683,6 +767,9 @@ struct sub_throws : super_throws { sub_throws() noexcept : super_throws() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions }; +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'sub_throws' +// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'sub_throws' +// CHECK-MESSAGES: :[[@LINE-9]]:36: note: frame #1: function 'super_throws' throws unhandled exception here struct init_member_throws { super_throws s; @@ -690,6 +777,8 @@ struct init_member_throws { init_member_throws() noexcept : s() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions }; +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'init_member_throws' +// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'init_member_throws' struct implicit_init_member_throws { super_throws s; @@ -697,6 +786,8 @@ struct implicit_init_member_throws { implicit_init_member_throws() noexcept {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions }; +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'implicit_init_member_throws' +// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'implicit_init_member_throws' struct init { explicit init(int, int) noexcept(false) { throw 42; } @@ -708,18 +799,25 @@ struct in_class_init_throws { in_class_init_throws() noexcept {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions }; +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'in_class_init_throws' +// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'in_class_init_throws' +// CHECK-MESSAGES: :[[@LINE-11]]:45: note: frame #1: function 'init' throws unhandled exception here int main() { // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions throw 1; return 0; } +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'main' +// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'main' throws unhandled exception here // The following function all incorrectly throw exceptions, *but* calling them // should not yield a warning because they are marked as noexcept. void test_basic_no_throw() noexcept { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'test_basic_no_throw' which should not throw exceptions +// CHECK-MESSAGES: :[[@LINE-2]]:6: note: example of unhandled exception throw stack, starting from function 'test_basic_no_throw' +// CHECK-MESSAGES: :[[@LINE-3]]:39: note: frame #0: function 'test_basic_no_throw' throws unhandled exception here void test_basic_throw() noexcept(false) { throw 42; } @@ -732,6 +830,9 @@ void calls_non_and_throwing() noexcept { test_basic_no_throw(); test_basic_throw(); } +// CHECK-MESSAGES: :[[@LINE-5]]:6: note: example of unhandled exception throw stack, starting from function 'calls_non_and_throwing' +// CHECK-MESSAGES: :[[@LINE-6]]:6: note: frame #0: function 'calls_non_and_throwing' +// CHECK-MESSAGES: :[[@LINE-13]]:43: note: frame #1: function 'test_basic_throw' throws unhandled exception here namespace PR55143 { namespace PR40583 { @@ -749,11 +850,17 @@ struct test_implicit_throw { test_implicit_throw(const test_implicit_throw&) { throw 42; } test_implicit_throw(test_implicit_throw&&) { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'test_implicit_throw' which should not throw exceptions + // CHECK-MESSAGES: :[[@LINE-2]]:5: note: example of unhandled exception throw stack, starting from function 'test_implicit_throw' + // CHECK-MESSAGES: :[[@LINE-3]]:50: note: frame #0: function 'test_implicit_throw' test_implicit_throw& operator=(const test_implicit_throw&) { throw 42; } test_implicit_throw& operator=(test_implicit_throw&&) { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: an exception may be thrown in function 'operator=' which should not throw exceptions + // CHECK-MESSAGES: :[[@LINE-2]]:26: note: example of unhandled exception throw stack, starting from function 'operator=' + // CHECK-MESSAGES: :[[@LINE-3]]:61: note: frame #0: function 'operator=' ~test_implicit_throw() { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function '~test_implicit_throw' which should not throw exceptions + // CHECK-MESSAGES: :[[@LINE-2]]:5: note: example of unhandled exception throw stack, starting from function '~test_implicit_throw' + // CHECK-MESSAGES: :[[@LINE-3]]:30: note: frame #0: function '~test_implicit_throw' }; }} From e42101646d906d34b6ac4f8568572624c5acf734 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Sun, 13 Apr 2025 23:04:38 +0300 Subject: [PATCH 2/4] added handling of unknown exceptions and renamed diagnostics --- .../bugprone/ExceptionEscapeCheck.cpp | 2 +- .../clang-tidy/utils/ExceptionAnalyzer.cpp | 10 +- .../bugprone/exception-escape-coro.cpp | 84 +++++++-------- .../bugprone/exception-escape-rethrow.cpp | 4 +- .../bugprone/exception-escape-throw.cpp | 9 +- .../checkers/bugprone/exception-escape.cpp | 100 +++++++++--------- 6 files changed, 107 insertions(+), 102 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 6574b36129f2c..6ba6a7fa84d7b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -100,7 +100,7 @@ void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) { // stack of thrown exception. const utils::ExceptionAnalyzer::CallStack &Stack = ThrowInfo.Stack; diag(Stack.front()->getLocation(), - "example of unhandled exception throw stack, starting from function %0", + "throw stack of unhandled exception, starting from function %0", DiagnosticIDs::Note) << Stack.front(); diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index c41b6f0a7a76a..1d8e6da777e82 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -491,9 +491,13 @@ ExceptionAnalyzer::throwsException(const FunctionDecl *Func, auto Result = ExceptionInfo::createUnknown(); if (const auto *FPT = Func->getType()->getAs()) { - for (const QualType &Ex : FPT->exceptions()) - // Nothing in ThrowInfo because there is no location of 'throw' - Result.registerException(Ex.getTypePtr(), {}); + for (const QualType &Ex : FPT->exceptions()) { + CallStack.insert(Func); + Result.registerException( + Ex.getTypePtr(), + {Func->getExceptionSpecSourceRange().getBegin(), CallStack}); + CallStack.remove(Func); + } } return Result; } diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp index 829ec30353b94..07b7a3d1b1904 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -221,7 +221,7 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-7]]:11: note: example of unhandled exception throw stack, starting from function 'c_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-7]]:11: note: throw stack of unhandled exception, starting from function 'c_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #0: function 'c_ShouldDiag' // CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here @@ -233,7 +233,7 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:17: note: example of unhandled exception throw stack, starting from function 'd_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:17: note: throw stack of unhandled exception, starting from function 'd_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:17: note: frame #0: function 'd_ShouldDiag' // CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' // CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here @@ -246,7 +246,7 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:24: note: example of unhandled exception throw stack, starting from function 'e_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:24: note: throw stack of unhandled exception, starting from function 'e_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #0: function 'e_ShouldDiag' // CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here @@ -258,7 +258,7 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:31: note: example of unhandled exception throw stack, starting from function 'f_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:31: note: throw stack of unhandled exception, starting from function 'f_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #0: function 'f_ShouldDiag' // CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here @@ -271,7 +271,7 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-5]]:38: note: example of unhandled exception throw stack, starting from function 'g_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:38: note: throw stack of unhandled exception, starting from function 'g_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #0: function 'g_ShouldDiag' // CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here @@ -285,7 +285,7 @@ Task h_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-5]]:45: note: example of unhandled exception throw stack, starting from function 'h_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:45: note: throw stack of unhandled exception, starting from function 'h_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #0: function 'h_ShouldDiag' // CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here @@ -315,7 +315,7 @@ j_ShouldDiag(const int a, const int b) noexcept { co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-7]]:1: note: example of unhandled exception throw stack, starting from function 'j_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-7]]:1: note: throw stack of unhandled exception, starting from function 'j_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here } // namespace coreturn @@ -350,7 +350,7 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-7]]:11: note: example of unhandled exception throw stack, starting from function 'c_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-7]]:11: note: throw stack of unhandled exception, starting from function 'c_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #0: function 'c_ShouldDiag' // CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here @@ -362,7 +362,7 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:17: note: example of unhandled exception throw stack, starting from function 'd_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:17: note: throw stack of unhandled exception, starting from function 'd_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:17: note: frame #0: function 'd_ShouldDiag' // CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' // CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here @@ -375,7 +375,7 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:24: note: example of unhandled exception throw stack, starting from function 'e_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:24: note: throw stack of unhandled exception, starting from function 'e_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #0: function 'e_ShouldDiag' // CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here @@ -387,7 +387,7 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:31: note: example of unhandled exception throw stack, starting from function 'f_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:31: note: throw stack of unhandled exception, starting from function 'f_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #0: function 'f_ShouldDiag' // CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here @@ -400,7 +400,7 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-5]]:38: note: example of unhandled exception throw stack, starting from function 'g_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:38: note: throw stack of unhandled exception, starting from function 'g_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #0: function 'g_ShouldDiag' // CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here @@ -414,7 +414,7 @@ Task h_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-5]]:45: note: example of unhandled exception throw stack, starting from function 'h_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:45: note: throw stack of unhandled exception, starting from function 'h_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #0: function 'h_ShouldDiag' // CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here @@ -444,7 +444,7 @@ j_ShouldDiag(const int a, const int b) noexcept { co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-7]]:1: note: example of unhandled exception throw stack, starting from function 'j_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-7]]:1: note: throw stack of unhandled exception, starting from function 'j_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here } // namespace coyield @@ -479,7 +479,7 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-7]]:12: note: example of unhandled exception throw stack, starting from function 'c_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-7]]:12: note: throw stack of unhandled exception, starting from function 'c_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #0: function 'c_ShouldDiag' // CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here @@ -491,7 +491,7 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-4]]:18: note: example of unhandled exception throw stack, starting from function 'd_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:18: note: throw stack of unhandled exception, starting from function 'd_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:18: note: frame #0: function 'd_ShouldDiag' // CHECK-MESSAGES: :153:8: note: frame #1: function 'get_return_object' // CHECK-MESSAGES: :81:7: note: frame #2: function 'Task' throws unhandled exception here @@ -504,7 +504,7 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-4]]:25: note: example of unhandled exception throw stack, starting from function 'e_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:25: note: throw stack of unhandled exception, starting from function 'e_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:25: note: frame #0: function 'e_ShouldDiag' // CHECK-MESSAGES: :149:7: note: frame #1: function 'Promise' throws unhandled exception here @@ -516,7 +516,7 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-4]]:32: note: example of unhandled exception throw stack, starting from function 'f_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:32: note: throw stack of unhandled exception, starting from function 'f_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:32: note: frame #0: function 'f_ShouldDiag' // CHECK-MESSAGES: :163:7: note: frame #1: function 'initial_suspend' throws unhandled exception here @@ -530,7 +530,7 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-5]]:39: note: example of unhandled exception throw stack, starting from function 'g_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-5]]:39: note: throw stack of unhandled exception, starting from function 'g_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-6]]:39: note: frame #0: function 'g_ShouldDiag' // CHECK-MESSAGES: :155:7: note: frame #1: function 'get_return_object' throws unhandled exception here @@ -544,7 +544,7 @@ h_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-4]]:1: note: example of unhandled exception throw stack, starting from function 'h_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-4]]:1: note: throw stack of unhandled exception, starting from function 'h_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-5]]:1: note: frame #0: function 'h_ShouldDiag' // CHECK-MESSAGES: :175:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here @@ -572,7 +572,7 @@ j_ShouldDiag(const int a, const int b) noexcept { if (b == 0) throw b; } -// CHECK-MESSAGES: :[[@LINE-6]]:1: note: example of unhandled exception throw stack, starting from function 'j_ShouldDiag' +// CHECK-MESSAGES: :[[@LINE-6]]:1: note: throw stack of unhandled exception, starting from function 'j_ShouldDiag' // CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here } // namespace coawait @@ -612,7 +612,7 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-7]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here @@ -625,7 +625,7 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' // CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here @@ -640,7 +640,7 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here @@ -654,7 +654,7 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here @@ -669,7 +669,7 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here @@ -685,7 +685,7 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here @@ -719,7 +719,7 @@ const auto j_ShouldDiag = co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-8]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-8]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' throws unhandled exception here } // namespace coreturn @@ -755,7 +755,7 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-7]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here @@ -768,7 +768,7 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' @@ -782,7 +782,7 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here @@ -796,7 +796,7 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here @@ -811,7 +811,7 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here @@ -827,7 +827,7 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here @@ -861,7 +861,7 @@ const auto j_ShouldDiag = co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-8]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-8]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' throws unhandled exception here } // namespace coyield @@ -897,7 +897,7 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-7]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here @@ -910,7 +910,7 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :153:8: note: frame #1: function 'get_return_object' @@ -924,7 +924,7 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' // CHECK-MESSAGES: :149:7: note: frame #1: function 'Promise' throws unhandled exception here @@ -938,7 +938,7 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :163:7: note: frame #1: function 'initial_suspend' throws unhandled exception here @@ -953,7 +953,7 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :155:7: note: frame #1: function 'get_return_object' throws unhandled exception here @@ -969,7 +969,7 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' // CHECK-MESSAGES: :175:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here @@ -1001,7 +1001,7 @@ const auto j_ShouldDiag = if (b == 0) throw b; }; -// CHECK-MESSAGES: :[[@LINE-7]]:5: note: example of unhandled exception throw stack, starting from function 'operator()' +// CHECK-MESSAGES: :[[@LINE-7]]:5: note: throw stack of unhandled exception, starting from function 'operator()' // CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: function 'operator()' throws unhandled exception here } // namespace coawait diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp index a58717fc7104b..b9b3dc63fbee4 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -22,7 +22,7 @@ int throwsAndCallsRethrower() noexcept { } return 1; } -// CHECK-MESSAGES: :[[@LINE-9]]:5: note: example of unhandled exception throw stack, starting from function 'throwsAndCallsRethrower' +// CHECK-MESSAGES: :[[@LINE-9]]:5: note: throw stack of unhandled exception, starting from function 'throwsAndCallsRethrower' // CHECK-MESSAGES: :[[@LINE-7]]:9: note: frame #0: function 'throwsAndCallsRethrower' throws unhandled exception here int throwsAndCallsCallsRethrower() noexcept { @@ -34,7 +34,7 @@ int throwsAndCallsCallsRethrower() noexcept { } return 1; } -// CHECK-MESSAGES: :[[@LINE-9]]:5: note: example of unhandled exception throw stack, starting from function 'throwsAndCallsCallsRethrower' +// CHECK-MESSAGES: :[[@LINE-9]]:5: note: throw stack of unhandled exception, starting from function 'throwsAndCallsCallsRethrower' // CHECK-MESSAGES: :[[@LINE-7]]:9: note: frame #0: function 'throwsAndCallsCallsRethrower' throws unhandled exception here void rethrowerNoexcept() noexcept { diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp index 1dd569de94af2..a50020d07041b 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp @@ -4,7 +4,7 @@ void throwing_throw_nothing() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'throwing_throw_nothing' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'throwing_throw_nothing' // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'throwing_throw_nothing' throws unhandled exception here void explicit_int_thrower() throw(int); @@ -17,7 +17,7 @@ void indirect_implicit() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions implicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'indirect_implicit' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'indirect_implicit' // CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_implicit' // CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #1: function 'implicit_int_thrower' throws unhandled exception here @@ -25,7 +25,8 @@ void indirect_explicit() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions explicit_int_thrower(); } -// FIXME: no diagnostics because 'explicit_int_thrower' has no explicit 'throw' expression +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: frame #0: function 'indirect_explicit' +// CHECK-MESSAGES: :[[@LINE-19]]:29: note: frame #1: function 'explicit_int_thrower' throws unhandled exception here struct super_throws { super_throws() throw(int) { throw 42; } @@ -35,6 +36,6 @@ struct sub_throws : super_throws { sub_throws() throw() : super_throws() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'sub_throws' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'sub_throws' // CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'sub_throws' // CHECK-MESSAGES: :[[@LINE-9]]:31: note: frame #1: function 'super_throws' throws unhandled exception here diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp index 8f9178eb64852..7863d14d393e6 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp @@ -12,7 +12,7 @@ struct throwing_destructor { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-5]]:3: note: example of unhandled exception throw stack, starting from function '~throwing_destructor' +// CHECK-MESSAGES: :[[@LINE-5]]:3: note: throw stack of unhandled exception, starting from function '~throwing_destructor' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function '~throwing_destructor' throws unhandled exception here struct throwing_move_constructor { @@ -21,7 +21,7 @@ struct throwing_move_constructor { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-5]]:3: note: example of unhandled exception throw stack, starting from function 'throwing_move_constructor' +// CHECK-MESSAGES: :[[@LINE-5]]:3: note: throw stack of unhandled exception, starting from function 'throwing_move_constructor' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throwing_move_constructor' throws unhandled exception here struct throwing_move_assignment { @@ -30,14 +30,14 @@ struct throwing_move_assignment { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-5]]:29: note: example of unhandled exception throw stack, starting from function 'operator=' +// CHECK-MESSAGES: :[[@LINE-5]]:29: note: throw stack of unhandled exception, starting from function 'operator=' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'operator=' throws unhandled exception here void throwing_noexcept() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'throwing_noexcept' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'throwing_noexcept' // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'throwing_noexcept' throws unhandled exception here void throw_and_catch() noexcept { @@ -56,7 +56,7 @@ void throw_and_catch_some(int n) noexcept { } catch(int &) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_and_catch_some' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_and_catch_some' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_and_catch_some' throws unhandled exception here void throw_and_catch_each(int n) noexcept { @@ -86,7 +86,7 @@ void throw_and_rethrow() noexcept { throw; } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_and_rethrow' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_and_rethrow' // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'throw_and_rethrow' throws unhandled exception here void throw_catch_throw() noexcept { @@ -97,7 +97,7 @@ void throw_catch_throw() noexcept { throw 2; } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_catch_throw' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_catch_throw' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_catch_throw' throws unhandled exception here void throw_catch_rethrow_the_rest(int n) noexcept { @@ -110,7 +110,7 @@ void throw_catch_rethrow_the_rest(int n) noexcept { throw; } } -// CHECK-MESSAGES: :[[@LINE-10]]:6: note: example of unhandled exception throw stack, starting from function 'throw_catch_rethrow_the_rest' +// CHECK-MESSAGES: :[[@LINE-10]]:6: note: throw stack of unhandled exception, starting from function 'throw_catch_rethrow_the_rest' // CHECK-MESSAGES: :[[@LINE-7]]:5: note: frame #0: function 'throw_catch_rethrow_the_rest' throws unhandled exception here void throw_catch_pointer_c() noexcept { @@ -142,7 +142,7 @@ void throw_catch_multi_ptr_1() noexcept { } catch (const char **) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_catch_multi_ptr_1' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_catch_multi_ptr_1' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_catch_multi_ptr_1' throws unhandled exception here void throw_catch_multi_ptr_2() noexcept { @@ -189,7 +189,7 @@ void throw_c_catch_pointer() noexcept { throw p; } catch(int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_c_catch_pointer' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_c_catch_pointer' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_c_catch_pointer' throws unhandled exception here void throw_c_catch_pointer_v() noexcept { @@ -200,7 +200,7 @@ void throw_c_catch_pointer_v() noexcept { throw p; } catch(volatile int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_c_catch_pointer_v' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_c_catch_pointer_v' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_c_catch_pointer_v' throws unhandled exception here void throw_v_catch_pointer() noexcept { @@ -211,7 +211,7 @@ void throw_v_catch_pointer() noexcept { throw p; } catch(int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_v_catch_pointer' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_v_catch_pointer' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_v_catch_pointer' throws unhandled exception here void throw_v_catch_pointer_c() noexcept { @@ -222,7 +222,7 @@ void throw_v_catch_pointer_c() noexcept { throw p; } catch(const int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_v_catch_pointer_c' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_v_catch_pointer_c' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_v_catch_pointer_c' throws unhandled exception here void throw_cv_catch_pointer_c() noexcept { @@ -233,7 +233,7 @@ void throw_cv_catch_pointer_c() noexcept { throw p; } catch(const int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_cv_catch_pointer_c' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_cv_catch_pointer_c' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_cv_catch_pointer_c' throws unhandled exception here void throw_cv_catch_pointer_v() noexcept { @@ -244,7 +244,7 @@ void throw_cv_catch_pointer_v() noexcept { throw p; } catch(volatile int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_cv_catch_pointer_v' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_cv_catch_pointer_v' // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_cv_catch_pointer_v' throws unhandled exception here class base {}; @@ -293,7 +293,7 @@ void throw_derived_catch_base_ptr() noexcept { } catch(base *) { } } -// CHECK-MESSAGES: :[[@LINE-9]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_ptr' +// CHECK-MESSAGES: :[[@LINE-9]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_ptr' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ptr' throws unhandled exception here class A {}; @@ -318,7 +318,7 @@ void throw_derived_catch_base_private() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_private' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_private' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_private' throws unhandled exception here void throw_derived_catch_base_private_ptr() noexcept { @@ -329,7 +329,7 @@ void throw_derived_catch_base_private_ptr() noexcept { } catch(A *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_private_ptr' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_private_ptr' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_private_ptr' throws unhandled exception here void throw_derived_catch_base_protected() noexcept { @@ -340,7 +340,7 @@ void throw_derived_catch_base_protected() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_protected' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_protected' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_protected' throws unhandled exception here void throw_derived_catch_base_protected_ptr() noexcept { @@ -351,7 +351,7 @@ void throw_derived_catch_base_protected_ptr() noexcept { } catch(A *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_protected_ptr' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_protected_ptr' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_protected_ptr' throws unhandled exception here void throw_derived_catch_base_ambiguous() noexcept { @@ -362,7 +362,7 @@ void throw_derived_catch_base_ambiguous() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_ambiguous' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_ambiguous' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ambiguous' throws unhandled exception here void throw_derived_catch_base_ambiguous_ptr() noexcept { @@ -373,7 +373,7 @@ void throw_derived_catch_base_ambiguous_ptr() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derived_catch_base_ambiguous_ptr' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_ambiguous_ptr' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ambiguous_ptr' throws unhandled exception here void throw_alias_catch_original() noexcept { @@ -396,7 +396,7 @@ void throw_alias_catch_original_warn() noexcept { } catch (int) { } } -// CHECK-MESSAGES: :[[@LINE-10]]:6: note: example of unhandled exception throw stack, starting from function 'throw_alias_catch_original_warn' +// CHECK-MESSAGES: :[[@LINE-10]]:6: note: throw stack of unhandled exception, starting from function 'throw_alias_catch_original_warn' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_alias_catch_original_warn' throws unhandled exception here void throw_original_catch_alias() noexcept { @@ -419,7 +419,7 @@ void throw_original_catch_alias_warn() noexcept { } catch (volatile const alias *const *) { } } -// CHECK-MESSAGES: :[[@LINE-10]]:6: note: example of unhandled exception throw stack, starting from function 'throw_original_catch_alias_warn' +// CHECK-MESSAGES: :[[@LINE-10]]:6: note: throw stack of unhandled exception, starting from function 'throw_original_catch_alias_warn' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_original_catch_alias_warn' throws unhandled exception here void throw_original_catch_alias_2() noexcept { @@ -481,7 +481,7 @@ void throw_basefn_catch_derivedfn() noexcept { } catch(void(derivedMember::*)()) { } } -// CHECK-MESSAGES: :[[@LINE-7]]:6: note: example of unhandled exception throw stack, starting from function 'throw_basefn_catch_derivedfn' +// CHECK-MESSAGES: :[[@LINE-7]]:6: note: throw stack of unhandled exception, starting from function 'throw_basefn_catch_derivedfn' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basefn_catch_derivedfn' throws unhandled exception here void throw_basefn_catch_basefn() noexcept { @@ -499,7 +499,7 @@ void throw_basem_catch_basem_throw() noexcept { } catch(const int* baseMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_basem_catch_basem_throw' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_basem_catch_basem_throw' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basem_catch_basem_throw' throws unhandled exception here void throw_basem_catch_basem() noexcept { @@ -518,7 +518,7 @@ void throw_basem_catch_derivedm() noexcept { } catch(const int* const derivedMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_basem_catch_derivedm' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_basem_catch_derivedm' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basem_catch_derivedm' throws unhandled exception here void throw_derivedm_catch_basem() noexcept { @@ -529,7 +529,7 @@ void throw_derivedm_catch_basem() noexcept { } catch(const int* const baseMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: example of unhandled exception throw stack, starting from function 'throw_derivedm_catch_basem' +// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derivedm_catch_basem' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derivedm_catch_basem' throws unhandled exception here void throw_original_catch_alias_2_warn() noexcept { @@ -542,7 +542,7 @@ void throw_original_catch_alias_2_warn() noexcept { } catch (volatile alias *) { } } -// CHECK-MESSAGES: :[[@LINE-10]]:6: note: example of unhandled exception throw stack, starting from function 'throw_original_catch_alias_2_warn' +// CHECK-MESSAGES: :[[@LINE-10]]:6: note: throw stack of unhandled exception, starting from function 'throw_original_catch_alias_2_warn' // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_original_catch_alias_2_warn' throws unhandled exception here void try_nested_try(int n) noexcept { @@ -568,7 +568,7 @@ void bad_try_nested_try(int n) noexcept { } catch(double &) { } } -// CHECK-MESSAGES: :[[@LINE-11]]:6: note: example of unhandled exception throw stack, starting from function 'bad_try_nested_try' +// CHECK-MESSAGES: :[[@LINE-11]]:6: note: throw stack of unhandled exception, starting from function 'bad_try_nested_try' // CHECK-MESSAGES: :[[@LINE-9]]:12: note: frame #0: function 'bad_try_nested_try' throws unhandled exception here void try_nested_catch() noexcept { @@ -607,7 +607,7 @@ void bad_catch_nested_try() noexcept { } catch(double &) { } } -// CHECK-MESSAGES: :[[@LINE-12]]:6: note: example of unhandled exception throw stack, starting from function 'bad_catch_nested_try' +// CHECK-MESSAGES: :[[@LINE-12]]:6: note: throw stack of unhandled exception, starting from function 'bad_catch_nested_try' // CHECK-MESSAGES: :[[@LINE-7]]:7: note: frame #0: function 'bad_catch_nested_try' throws unhandled exception here void implicit_int_thrower() { @@ -622,7 +622,7 @@ void indirect_implicit() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions implicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'indirect_implicit' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'indirect_implicit' // CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_implicit' // CHECK-MESSAGES: :[[@LINE-13]]:3: note: frame #1: function 'implicit_int_thrower' throws unhandled exception here @@ -630,7 +630,7 @@ void indirect_explicit() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions explicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'indirect_explicit' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'indirect_explicit' // CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_explicit' // CHECK-MESSAGES: :[[@LINE-17]]:3: note: frame #1: function 'explicit_int_thrower' throws unhandled exception here @@ -653,21 +653,21 @@ void swap(int&, int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'swap' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'swap' // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'swap' throws unhandled exception here void iter_swap(int&, int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'iter_swap' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'iter_swap' // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'iter_swap' throws unhandled exception here void iter_move(int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'iter_move' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'iter_move' // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'iter_move' throws unhandled exception here namespace std { @@ -687,14 +687,14 @@ void enabled1() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'enabled1' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'enabled1' // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'enabled1' throws unhandled exception here void enabled2() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions enabled1(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: example of unhandled exception throw stack, starting from function 'enabled2' +// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'enabled2' // CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'enabled2' // CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #1: function 'enabled1' throws unhandled exception here @@ -728,7 +728,7 @@ void this_counts(int n) noexcept { if (n) throw 1; throw ignored1(); } -// CHECK-MESSAGES: :[[@LINE-5]]:6: note: example of unhandled exception throw stack, starting from function 'this_counts' +// CHECK-MESSAGES: :[[@LINE-5]]:6: note: throw stack of unhandled exception, starting from function 'this_counts' // CHECK-MESSAGES: :[[@LINE-4]]:10: note: frame #0: function 'this_counts' throws unhandled exception here void thrower(int n) { @@ -741,7 +741,7 @@ int directly_recursive(int n) noexcept { thrower(n); return directly_recursive(n); } -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: example of unhandled exception throw stack, starting from function 'directly_recursive' +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: throw stack of unhandled exception, starting from function 'directly_recursive' // CHECK-MESSAGES: :[[@LINE-7]]:5: note: frame #0: function 'directly_recursive' // CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #1: function 'thrower' throws unhandled exception here @@ -767,7 +767,7 @@ struct sub_throws : super_throws { sub_throws() noexcept : super_throws() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'sub_throws' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'sub_throws' // CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'sub_throws' // CHECK-MESSAGES: :[[@LINE-9]]:36: note: frame #1: function 'super_throws' throws unhandled exception here @@ -777,7 +777,7 @@ struct init_member_throws { init_member_throws() noexcept : s() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'init_member_throws' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'init_member_throws' // CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'init_member_throws' struct implicit_init_member_throws { @@ -786,7 +786,7 @@ struct implicit_init_member_throws { implicit_init_member_throws() noexcept {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'implicit_init_member_throws' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'implicit_init_member_throws' // CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'implicit_init_member_throws' struct init { @@ -799,7 +799,7 @@ struct in_class_init_throws { in_class_init_throws() noexcept {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: example of unhandled exception throw stack, starting from function 'in_class_init_throws' +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'in_class_init_throws' // CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'in_class_init_throws' // CHECK-MESSAGES: :[[@LINE-11]]:45: note: frame #1: function 'init' throws unhandled exception here @@ -808,7 +808,7 @@ int main() { throw 1; return 0; } -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: example of unhandled exception throw stack, starting from function 'main' +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'main' // CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'main' throws unhandled exception here // The following function all incorrectly throw exceptions, *but* calling them @@ -816,7 +816,7 @@ int main() { void test_basic_no_throw() noexcept { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'test_basic_no_throw' which should not throw exceptions -// CHECK-MESSAGES: :[[@LINE-2]]:6: note: example of unhandled exception throw stack, starting from function 'test_basic_no_throw' +// CHECK-MESSAGES: :[[@LINE-2]]:6: note: throw stack of unhandled exception, starting from function 'test_basic_no_throw' // CHECK-MESSAGES: :[[@LINE-3]]:39: note: frame #0: function 'test_basic_no_throw' throws unhandled exception here void test_basic_throw() noexcept(false) { throw 42; } @@ -830,7 +830,7 @@ void calls_non_and_throwing() noexcept { test_basic_no_throw(); test_basic_throw(); } -// CHECK-MESSAGES: :[[@LINE-5]]:6: note: example of unhandled exception throw stack, starting from function 'calls_non_and_throwing' +// CHECK-MESSAGES: :[[@LINE-5]]:6: note: throw stack of unhandled exception, starting from function 'calls_non_and_throwing' // CHECK-MESSAGES: :[[@LINE-6]]:6: note: frame #0: function 'calls_non_and_throwing' // CHECK-MESSAGES: :[[@LINE-13]]:43: note: frame #1: function 'test_basic_throw' throws unhandled exception here @@ -850,16 +850,16 @@ struct test_implicit_throw { test_implicit_throw(const test_implicit_throw&) { throw 42; } test_implicit_throw(test_implicit_throw&&) { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'test_implicit_throw' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:5: note: example of unhandled exception throw stack, starting from function 'test_implicit_throw' + // CHECK-MESSAGES: :[[@LINE-2]]:5: note: throw stack of unhandled exception, starting from function 'test_implicit_throw' // CHECK-MESSAGES: :[[@LINE-3]]:50: note: frame #0: function 'test_implicit_throw' test_implicit_throw& operator=(const test_implicit_throw&) { throw 42; } test_implicit_throw& operator=(test_implicit_throw&&) { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: an exception may be thrown in function 'operator=' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:26: note: example of unhandled exception throw stack, starting from function 'operator=' + // CHECK-MESSAGES: :[[@LINE-2]]:26: note: throw stack of unhandled exception, starting from function 'operator=' // CHECK-MESSAGES: :[[@LINE-3]]:61: note: frame #0: function 'operator=' ~test_implicit_throw() { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function '~test_implicit_throw' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:5: note: example of unhandled exception throw stack, starting from function '~test_implicit_throw' + // CHECK-MESSAGES: :[[@LINE-2]]:5: note: throw stack of unhandled exception, starting from function '~test_implicit_throw' // CHECK-MESSAGES: :[[@LINE-3]]:30: note: frame #0: function '~test_implicit_throw' }; From 8afa0305995274ea56fcac1cc941010cb3be24ae Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 16 Apr 2025 23:30:17 +0300 Subject: [PATCH 3/4] added call-places of functions --- .../bugprone/ExceptionEscapeCheck.cpp | 31 +-- .../clang-tidy/utils/ExceptionAnalyzer.cpp | 30 +-- .../clang-tidy/utils/ExceptionAnalyzer.h | 8 +- .../bugprone/exception-escape-coro.cpp | 210 +++++++----------- .../bugprone/exception-escape-rethrow.cpp | 8 +- .../bugprone/exception-escape-throw.cpp | 17 +- .../checkers/bugprone/exception-escape.cpp | 168 +++++--------- 7 files changed, 190 insertions(+), 282 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 6ba6a7fa84d7b..012ed598b76cd 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -96,25 +96,26 @@ void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) { return; } - // FIXME: We should provide exact position of functions calls, not only call - // stack of thrown exception. const utils::ExceptionAnalyzer::CallStack &Stack = ThrowInfo.Stack; - diag(Stack.front()->getLocation(), - "throw stack of unhandled exception, starting from function %0", + diag(ThrowInfo.Loc, + "frame #0: unhandled exception may be thrown in function %0 here", DiagnosticIDs::Note) - << Stack.front(); - - size_t FrameNo = 0; - for (const FunctionDecl *CallNode : Stack) { - if (FrameNo != Stack.size() - 1) { - diag(CallNode->getLocation(), "frame #%0: function %1", + << Stack.back().first; + + size_t FrameNo = 1; + for (auto CurrIt = ++Stack.rbegin(), PrevIt = Stack.rbegin(); + CurrIt != Stack.rend(); ++CurrIt, ++PrevIt) { + const FunctionDecl *CurrFunction = CurrIt->first; + const FunctionDecl *PrevFunction = PrevIt->first; + const SourceLocation PrevLocation = PrevIt->second; + if (PrevLocation.isValid()) { + diag(PrevLocation, "frame #%0: function %1 calls function %2 here", DiagnosticIDs::Note) - << FrameNo << CallNode; + << FrameNo << CurrFunction << PrevFunction; } else { - diag(ThrowInfo.Loc, - "frame #%0: function %1 throws unhandled exception here", - DiagnosticIDs::Note) - << FrameNo << CallNode; + diag(CurrFunction->getLocation(), + "frame #%0: function %1 calls function %2", DiagnosticIDs::Note) + << FrameNo << CurrFunction << PrevFunction; } ++FrameNo; } diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp index 1d8e6da777e82..3fe8412e69675 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp @@ -464,16 +464,15 @@ void ExceptionAnalyzer::ExceptionInfo::reevaluateBehaviour() { else Behaviour = State::Throwing; } -ExceptionAnalyzer::ExceptionInfo -ExceptionAnalyzer::throwsException(const FunctionDecl *Func, - const ExceptionInfo::Throwables &Caught, - CallStack &CallStack) { +ExceptionAnalyzer::ExceptionInfo ExceptionAnalyzer::throwsException( + const FunctionDecl *Func, const ExceptionInfo::Throwables &Caught, + CallStack &CallStack, SourceLocation CallLoc) { if (!Func || CallStack.contains(Func) || (!CallStack.empty() && !canThrow(Func))) return ExceptionInfo::createNonThrowing(); if (const Stmt *Body = Func->getBody()) { - CallStack.insert(Func); + CallStack.insert({Func, CallLoc}); ExceptionInfo Result = throwsException(Body, Caught, CallStack); // For a constructor, we also have to check the initializers. @@ -485,18 +484,18 @@ ExceptionAnalyzer::throwsException(const FunctionDecl *Func, } } - CallStack.remove(Func); + CallStack.erase(Func); return Result; } auto Result = ExceptionInfo::createUnknown(); if (const auto *FPT = Func->getType()->getAs()) { for (const QualType &Ex : FPT->exceptions()) { - CallStack.insert(Func); + CallStack.insert({Func, CallLoc}); Result.registerException( Ex.getTypePtr(), {Func->getExceptionSpecSourceRange().getBegin(), CallStack}); - CallStack.remove(Func); + CallStack.erase(Func); } } return Result; @@ -566,12 +565,13 @@ ExceptionAnalyzer::throwsException(const Stmt *St, Results.merge(Uncaught); } else if (const auto *Call = dyn_cast(St)) { if (const FunctionDecl *Func = Call->getDirectCallee()) { - ExceptionInfo Excs = throwsException(Func, Caught, CallStack); + ExceptionInfo Excs = + throwsException(Func, Caught, CallStack, Call->getBeginLoc()); Results.merge(Excs); } } else if (const auto *Construct = dyn_cast(St)) { - ExceptionInfo Excs = - throwsException(Construct->getConstructor(), Caught, CallStack); + ExceptionInfo Excs = throwsException(Construct->getConstructor(), Caught, + CallStack, Construct->getBeginLoc()); Results.merge(Excs); } else if (const auto *DefaultInit = dyn_cast(St)) { ExceptionInfo Excs = @@ -590,8 +590,8 @@ ExceptionAnalyzer::throwsException(const Stmt *St, for (const auto &Exception : Excs.getExceptions()) { const Type *ExcType = Exception.getFirst(); if (const CXXRecordDecl *ThrowableRec = ExcType->getAsCXXRecordDecl()) { - ExceptionInfo DestructorExcs = - throwsException(ThrowableRec->getDestructor(), Caught, CallStack); + ExceptionInfo DestructorExcs = throwsException( + ThrowableRec->getDestructor(), Caught, CallStack, SourceLocation{}); Results.merge(DestructorExcs); } } @@ -612,8 +612,8 @@ ExceptionAnalyzer::analyzeImpl(const FunctionDecl *Func) { const auto CacheEntry = FunctionCache.find(Func); if (CacheEntry == FunctionCache.end()) { CallStack CallStack; - ExceptionList = - throwsException(Func, ExceptionInfo::Throwables(), CallStack); + ExceptionList = throwsException(Func, ExceptionInfo::Throwables(), + CallStack, Func->getLocation()); // Cache the result of the analysis. This is done prior to filtering // because it is best to keep as much information as possible. diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h index 0fea44fc8a622..bd466c99c04bb 100644 --- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h +++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.h @@ -29,11 +29,9 @@ class ExceptionAnalyzer { ///< definition. }; - /// We use a SetVector to preserve the order of the functions in the call + /// We use a MapVector to preserve the order of the functions in the call /// stack as well as have fast lookup. - using CallStack = llvm::SetVector, - llvm::DenseSet, 32>; + using CallStack = llvm::MapVector; /// Bundle the gathered information about an entity like a function regarding /// it's exception behaviour. The 'NonThrowing'-state can be considered as the @@ -144,7 +142,7 @@ class ExceptionAnalyzer { private: ExceptionInfo throwsException(const FunctionDecl *Func, const ExceptionInfo::Throwables &Caught, - CallStack &CallStack); + CallStack &CallStack, SourceLocation CallLoc); ExceptionInfo throwsException(const Stmt *St, const ExceptionInfo::Throwables &Caught, CallStack &CallStack); diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp index 07b7a3d1b1904..bf0a358353a9f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++20 %s bugprone-exception-escape %t -- \ +// RUN: %check_clang_tidy -std=c++20-or-later %s bugprone-exception-escape %t -- \ // RUN: -- -fexceptions -Wno-error=return-type namespace std { @@ -221,9 +221,8 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-7]]:11: note: throw stack of unhandled exception, starting from function 'c_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #0: function 'c_ShouldDiag' -// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #1: function 'c_ShouldDiag' calls function '~Evil' Task d_ShouldNotDiag(const int a, const int b) { co_return a / b; @@ -233,10 +232,9 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:17: note: throw stack of unhandled exception, starting from function 'd_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:17: note: frame #0: function 'd_ShouldDiag' -// CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' -// CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here +// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here +// CHECK-MESSAGES: :[[@LINE-6]]:17: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here Task e_ShouldNotDiag(const int a, const int b) { co_return a / b; @@ -246,9 +244,8 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:24: note: throw stack of unhandled exception, starting from function 'e_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #0: function 'e_ShouldDiag' -// CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here +// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here Task f_ShouldNotDiag(const int a, const int b) { co_return a / b; @@ -258,9 +255,8 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:31: note: throw stack of unhandled exception, starting from function 'f_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #0: function 'f_ShouldDiag' -// CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here +// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here Task g_ShouldNotDiag(const int a, const int b) { co_return a / b; @@ -271,9 +267,8 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-5]]:38: note: throw stack of unhandled exception, starting from function 'g_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #0: function 'g_ShouldDiag' -// CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here +// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here Task h_ShouldNotDiag(const int a, const int b) { @@ -285,9 +280,8 @@ Task h_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-5]]:45: note: throw stack of unhandled exception, starting from function 'h_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #0: function 'h_ShouldDiag' -// CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here +// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here Task i_ShouldNotDiag(const int a, const int b) { @@ -315,8 +309,7 @@ j_ShouldDiag(const int a, const int b) noexcept { co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-7]]:1: note: throw stack of unhandled exception, starting from function 'j_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'j_ShouldDiag' here } // namespace coreturn @@ -350,9 +343,8 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-7]]:11: note: throw stack of unhandled exception, starting from function 'c_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #0: function 'c_ShouldDiag' -// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #1: function 'c_ShouldDiag' calls function '~Evil' Task d_ShouldNotDiag(const int a, const int b) { co_yield a / b; @@ -362,10 +354,9 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:17: note: throw stack of unhandled exception, starting from function 'd_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:17: note: frame #0: function 'd_ShouldDiag' -// CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' -// CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here +// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here +// CHECK-MESSAGES: :[[@LINE-6]]:17: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here Task e_ShouldNotDiag(const int a, const int b) { co_yield a / b; @@ -375,9 +366,8 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:24: note: throw stack of unhandled exception, starting from function 'e_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #0: function 'e_ShouldDiag' -// CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here +// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here Task f_ShouldNotDiag(const int a, const int b) { co_yield a / b; @@ -387,9 +377,8 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:31: note: throw stack of unhandled exception, starting from function 'f_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #0: function 'f_ShouldDiag' -// CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here +// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here Task g_ShouldNotDiag(const int a, const int b) { co_yield a / b; @@ -400,9 +389,8 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-5]]:38: note: throw stack of unhandled exception, starting from function 'g_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #0: function 'g_ShouldDiag' -// CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here +// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here Task h_ShouldNotDiag(const int a, const int b) { @@ -414,9 +402,8 @@ Task h_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-5]]:45: note: throw stack of unhandled exception, starting from function 'h_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #0: function 'h_ShouldDiag' -// CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here +// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here Task i_ShouldNotDiag(const int a, const int b) { @@ -444,8 +431,7 @@ j_ShouldDiag(const int a, const int b) noexcept { co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-7]]:1: note: throw stack of unhandled exception, starting from function 'j_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'j_ShouldDiag' here } // namespace coyield @@ -479,9 +465,8 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-7]]:12: note: throw stack of unhandled exception, starting from function 'c_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #0: function 'c_ShouldDiag' -// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #1: function 'c_ShouldDiag' calls function '~Evil' Task d_ShouldNotDiag(const int a, const int b) { co_await returnOne(); @@ -491,10 +476,9 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-4]]:18: note: throw stack of unhandled exception, starting from function 'd_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:18: note: frame #0: function 'd_ShouldDiag' -// CHECK-MESSAGES: :153:8: note: frame #1: function 'get_return_object' -// CHECK-MESSAGES: :81:7: note: frame #2: function 'Task' throws unhandled exception here +// CHECK-MESSAGES: :81:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :158:12: note: frame #1: function 'get_return_object' calls function 'Task' here +// CHECK-MESSAGES: :[[@LINE-6]]:18: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here Task e_ShouldNotDiag(const int a, const int b) { co_await returnOne(); @@ -504,9 +488,8 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-4]]:25: note: throw stack of unhandled exception, starting from function 'e_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:25: note: frame #0: function 'e_ShouldDiag' -// CHECK-MESSAGES: :149:7: note: frame #1: function 'Promise' throws unhandled exception here +// CHECK-MESSAGES: :149:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :[[@LINE-5]]:25: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here Task f_ShouldNotDiag(const int a, const int b) { co_await returnOne(); @@ -516,9 +499,8 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-4]]:32: note: throw stack of unhandled exception, starting from function 'f_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:32: note: frame #0: function 'f_ShouldDiag' -// CHECK-MESSAGES: :163:7: note: frame #1: function 'initial_suspend' throws unhandled exception here +// CHECK-MESSAGES: :163:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :[[@LINE-5]]:32: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here Task g_ShouldNotDiag(const int a, const int b) { @@ -530,9 +512,8 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-5]]:39: note: throw stack of unhandled exception, starting from function 'g_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-6]]:39: note: frame #0: function 'g_ShouldDiag' -// CHECK-MESSAGES: :155:7: note: frame #1: function 'get_return_object' throws unhandled exception here +// CHECK-MESSAGES: :155:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :[[@LINE-6]]:39: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here Task h_ShouldNotDiag(const int a, const int b) { @@ -544,9 +525,8 @@ h_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :[[@LINE-4]]:1: note: throw stack of unhandled exception, starting from function 'h_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-5]]:1: note: frame #0: function 'h_ShouldDiag' -// CHECK-MESSAGES: :175:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here +// CHECK-MESSAGES: :175:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :[[@LINE-5]]:1: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here Task i_ShouldNotDiag(const int a, const int b) { @@ -572,8 +552,7 @@ j_ShouldDiag(const int a, const int b) noexcept { if (b == 0) throw b; } -// CHECK-MESSAGES: :[[@LINE-6]]:1: note: throw stack of unhandled exception, starting from function 'j_ShouldDiag' -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: function 'j_ShouldDiag' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:5: note: frame #0: unhandled exception may be thrown in function 'j_ShouldDiag' here } // namespace coawait @@ -612,9 +591,8 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-7]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil' const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { co_return a / b; @@ -625,10 +603,9 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' -// CHECK-MESSAGES: :54:7: note: frame #2: function 'Task' throws unhandled exception here +// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here const auto e_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -640,9 +617,8 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here +// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here const auto f_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -654,9 +630,8 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here +// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here const auto g_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -669,9 +644,8 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here +// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here const auto h_ShouldNotDiag = [](const int a, @@ -685,9 +659,8 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here +// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here const auto i_ShouldNotDiag = [](const int a, @@ -719,8 +692,7 @@ const auto j_ShouldDiag = co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-8]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'operator()' here } // namespace coreturn @@ -755,9 +727,8 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-7]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil' const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { co_yield a / b; @@ -768,9 +739,9 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :104:8: note: frame #1: function 'get_return_object' +// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here const auto e_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -782,9 +753,8 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :100:7: note: frame #1: function 'Promise' throws unhandled exception here +// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here const auto f_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -796,9 +766,8 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :114:7: note: frame #1: function 'initial_suspend' throws unhandled exception here +// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here const auto g_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -811,9 +780,8 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :106:7: note: frame #1: function 'get_return_object' throws unhandled exception here +// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here const auto h_ShouldNotDiag = [](const int a, @@ -827,9 +795,8 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :133:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here +// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here const auto i_ShouldNotDiag = [](const int a, @@ -861,8 +828,7 @@ const auto j_ShouldDiag = co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-8]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'operator()' here } // namespace coyield @@ -897,9 +863,8 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-7]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :186:5: note: frame #1: function '~Evil' throws unhandled exception here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil' const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { co_await returnOne(); @@ -910,9 +875,9 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :153:8: note: frame #1: function 'get_return_object' +// CHECK-MESSAGES: :81:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :158:12: note: frame #1: function 'get_return_object' calls function 'Task' here +// CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here const auto e_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -924,9 +889,8 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-5]]:27: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :149:7: note: frame #1: function 'Promise' throws unhandled exception here +// CHECK-MESSAGES: :149:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here const auto f_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -938,9 +902,8 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :163:7: note: frame #1: function 'initial_suspend' throws unhandled exception here +// CHECK-MESSAGES: :163:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here const auto g_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -953,9 +916,8 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :155:7: note: frame #1: function 'get_return_object' throws unhandled exception here +// CHECK-MESSAGES: :155:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here const auto h_ShouldNotDiag = [](const int a, @@ -969,9 +931,8 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'operator()' -// CHECK-MESSAGES: :175:7: note: frame #1: function 'unhandled_exception' throws unhandled exception here +// CHECK-MESSAGES: :175:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here const auto i_ShouldNotDiag = [](const int a, @@ -1001,8 +962,7 @@ const auto j_ShouldDiag = if (b == 0) throw b; }; -// CHECK-MESSAGES: :[[@LINE-7]]:5: note: throw stack of unhandled exception, starting from function 'operator()' -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: function 'operator()' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:5: note: frame #0: unhandled exception may be thrown in function 'operator()' here } // namespace coawait diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp index b9b3dc63fbee4..7ac5aeb6428b6 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy -std=c++11,c++14,c++17,c++20 %s bugprone-exception-escape %t -- \ +// RUN: %check_clang_tidy -std=c++11-or-later %s bugprone-exception-escape %t -- \ // RUN: -- -fexceptions void rethrower() { @@ -22,8 +22,7 @@ int throwsAndCallsRethrower() noexcept { } return 1; } -// CHECK-MESSAGES: :[[@LINE-9]]:5: note: throw stack of unhandled exception, starting from function 'throwsAndCallsRethrower' -// CHECK-MESSAGES: :[[@LINE-7]]:9: note: frame #0: function 'throwsAndCallsRethrower' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #0: unhandled exception may be thrown in function 'throwsAndCallsRethrower' here int throwsAndCallsCallsRethrower() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions @@ -34,8 +33,7 @@ int throwsAndCallsCallsRethrower() noexcept { } return 1; } -// CHECK-MESSAGES: :[[@LINE-9]]:5: note: throw stack of unhandled exception, starting from function 'throwsAndCallsCallsRethrower' -// CHECK-MESSAGES: :[[@LINE-7]]:9: note: frame #0: function 'throwsAndCallsCallsRethrower' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #0: unhandled exception may be thrown in function 'throwsAndCallsCallsRethrower' here void rethrowerNoexcept() noexcept { throw; diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp index a50020d07041b..dc29b6593243a 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp @@ -4,8 +4,7 @@ void throwing_throw_nothing() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'throwing_throw_nothing' -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'throwing_throw_nothing' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'throwing_throw_nothing' here void explicit_int_thrower() throw(int); @@ -17,16 +16,15 @@ void indirect_implicit() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions implicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'indirect_implicit' -// CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_implicit' -// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #1: function 'implicit_int_thrower' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-7]]:3: note: frame #0: unhandled exception may be thrown in function 'implicit_int_thrower' here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_implicit' calls function 'implicit_int_thrower' here void indirect_explicit() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions explicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: frame #0: function 'indirect_explicit' -// CHECK-MESSAGES: :[[@LINE-19]]:29: note: frame #1: function 'explicit_int_thrower' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-17]]:29: note: frame #0: unhandled exception may be thrown in function 'explicit_int_thrower' here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_explicit' calls function 'explicit_int_thrower' here struct super_throws { super_throws() throw(int) { throw 42; } @@ -36,6 +34,5 @@ struct sub_throws : super_throws { sub_throws() throw() : super_throws() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'sub_throws' -// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'sub_throws' -// CHECK-MESSAGES: :[[@LINE-9]]:31: note: frame #1: function 'super_throws' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-7]]:31: note: frame #0: unhandled exception may be thrown in function 'super_throws' here +// CHECK-MESSAGES: :[[@LINE-4]]:26: note: frame #1: function 'sub_throws' calls function 'super_throws' here diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp index 7863d14d393e6..4313b105a6430 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp @@ -12,8 +12,7 @@ struct throwing_destructor { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-5]]:3: note: throw stack of unhandled exception, starting from function '~throwing_destructor' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function '~throwing_destructor' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function '~throwing_destructor' here struct throwing_move_constructor { throwing_move_constructor(throwing_move_constructor&&) { @@ -21,8 +20,7 @@ struct throwing_move_constructor { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-5]]:3: note: throw stack of unhandled exception, starting from function 'throwing_move_constructor' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throwing_move_constructor' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throwing_move_constructor' here struct throwing_move_assignment { throwing_move_assignment& operator=(throwing_move_assignment&&) { @@ -30,15 +28,13 @@ struct throwing_move_assignment { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-5]]:29: note: throw stack of unhandled exception, starting from function 'operator=' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'operator=' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'operator=' here void throwing_noexcept() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'throwing_noexcept' -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'throwing_noexcept' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'throwing_noexcept' here void throw_and_catch() noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions @@ -56,8 +52,7 @@ void throw_and_catch_some(int n) noexcept { } catch(int &) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_and_catch_some' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_and_catch_some' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_and_catch_some' here void throw_and_catch_each(int n) noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions @@ -86,8 +81,7 @@ void throw_and_rethrow() noexcept { throw; } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_and_rethrow' -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: function 'throw_and_rethrow' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_and_rethrow' here void throw_catch_throw() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions @@ -97,8 +91,7 @@ void throw_catch_throw() noexcept { throw 2; } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_catch_throw' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_catch_throw' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_catch_throw' here void throw_catch_rethrow_the_rest(int n) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions @@ -110,8 +103,7 @@ void throw_catch_rethrow_the_rest(int n) noexcept { throw; } } -// CHECK-MESSAGES: :[[@LINE-10]]:6: note: throw stack of unhandled exception, starting from function 'throw_catch_rethrow_the_rest' -// CHECK-MESSAGES: :[[@LINE-7]]:5: note: frame #0: function 'throw_catch_rethrow_the_rest' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_catch_rethrow_the_rest' here void throw_catch_pointer_c() noexcept { try { @@ -142,8 +134,7 @@ void throw_catch_multi_ptr_1() noexcept { } catch (const char **) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_catch_multi_ptr_1' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_catch_multi_ptr_1' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_catch_multi_ptr_1' here void throw_catch_multi_ptr_2() noexcept { try { @@ -189,8 +180,7 @@ void throw_c_catch_pointer() noexcept { throw p; } catch(int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_c_catch_pointer' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_c_catch_pointer' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_c_catch_pointer' here 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 @@ -200,8 +190,7 @@ void throw_c_catch_pointer_v() noexcept { throw p; } catch(volatile int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_c_catch_pointer_v' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_c_catch_pointer_v' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_c_catch_pointer_v' here 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 @@ -211,8 +200,7 @@ void throw_v_catch_pointer() noexcept { throw p; } catch(int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_v_catch_pointer' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_v_catch_pointer' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_v_catch_pointer' here 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 @@ -222,8 +210,7 @@ void throw_v_catch_pointer_c() noexcept { throw p; } catch(const int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_v_catch_pointer_c' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_v_catch_pointer_c' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_v_catch_pointer_c' here 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 @@ -233,8 +220,7 @@ void throw_cv_catch_pointer_c() noexcept { throw p; } catch(const int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_cv_catch_pointer_c' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_cv_catch_pointer_c' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_cv_catch_pointer_c' here 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 @@ -244,8 +230,7 @@ void throw_cv_catch_pointer_v() noexcept { throw p; } catch(volatile int *) {} } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_cv_catch_pointer_v' -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: function 'throw_cv_catch_pointer_v' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_cv_catch_pointer_v' here class base {}; class derived: public base {}; @@ -293,8 +278,7 @@ void throw_derived_catch_base_ptr() noexcept { } catch(base *) { } } -// CHECK-MESSAGES: :[[@LINE-9]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_ptr' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ptr' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_ptr' here class A {}; class B : A {}; @@ -318,8 +302,7 @@ void throw_derived_catch_base_private() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_private' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_private' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_private' here void throw_derived_catch_base_private_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private_ptr' which should not throw exceptions @@ -329,8 +312,7 @@ void throw_derived_catch_base_private_ptr() noexcept { } catch(A *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_private_ptr' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_private_ptr' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_private_ptr' here void throw_derived_catch_base_protected() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected' which should not throw exceptions @@ -340,8 +322,7 @@ void throw_derived_catch_base_protected() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_protected' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_protected' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_protected' here void throw_derived_catch_base_protected_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected_ptr' which should not throw exceptions @@ -351,8 +332,7 @@ void throw_derived_catch_base_protected_ptr() noexcept { } catch(A *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_protected_ptr' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_protected_ptr' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_protected_ptr' here void throw_derived_catch_base_ambiguous() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous' which should not throw exceptions @@ -362,8 +342,7 @@ void throw_derived_catch_base_ambiguous() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_ambiguous' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ambiguous' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_ambiguous' here void throw_derived_catch_base_ambiguous_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' which should not throw exceptions @@ -373,8 +352,7 @@ void throw_derived_catch_base_ambiguous_ptr() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derived_catch_base_ambiguous_ptr' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derived_catch_base_ambiguous_ptr' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' here void throw_alias_catch_original() noexcept { using alias = int; @@ -396,8 +374,7 @@ void throw_alias_catch_original_warn() noexcept { } catch (int) { } } -// CHECK-MESSAGES: :[[@LINE-10]]:6: note: throw stack of unhandled exception, starting from function 'throw_alias_catch_original_warn' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_alias_catch_original_warn' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_alias_catch_original_warn' here void throw_original_catch_alias() noexcept { using alias = char; @@ -419,8 +396,7 @@ void throw_original_catch_alias_warn() noexcept { } catch (volatile const alias *const *) { } } -// CHECK-MESSAGES: :[[@LINE-10]]:6: note: throw stack of unhandled exception, starting from function 'throw_original_catch_alias_warn' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_original_catch_alias_warn' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_original_catch_alias_warn' here void throw_original_catch_alias_2() noexcept { using alias = const char *const; @@ -481,8 +457,7 @@ void throw_basefn_catch_derivedfn() noexcept { } catch(void(derivedMember::*)()) { } } -// CHECK-MESSAGES: :[[@LINE-7]]:6: note: throw stack of unhandled exception, starting from function 'throw_basefn_catch_derivedfn' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basefn_catch_derivedfn' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_basefn_catch_derivedfn' here void throw_basefn_catch_basefn() noexcept { try { @@ -499,8 +474,7 @@ void throw_basem_catch_basem_throw() noexcept { } catch(const int* baseMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_basem_catch_basem_throw' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basem_catch_basem_throw' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_basem_catch_basem_throw' here void throw_basem_catch_basem() noexcept { try { @@ -518,8 +492,7 @@ void throw_basem_catch_derivedm() noexcept { } catch(const int* const derivedMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_basem_catch_derivedm' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_basem_catch_derivedm' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_basem_catch_derivedm' here void throw_derivedm_catch_basem() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derivedm_catch_basem' which should not throw exceptions @@ -529,8 +502,7 @@ void throw_derivedm_catch_basem() noexcept { } catch(const int* const baseMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:6: note: throw stack of unhandled exception, starting from function 'throw_derivedm_catch_basem' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_derivedm_catch_basem' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derivedm_catch_basem' here void throw_original_catch_alias_2_warn() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_2_warn' which should not throw exceptions @@ -542,8 +514,7 @@ void throw_original_catch_alias_2_warn() noexcept { } catch (volatile alias *) { } } -// CHECK-MESSAGES: :[[@LINE-10]]:6: note: throw stack of unhandled exception, starting from function 'throw_original_catch_alias_2_warn' -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: function 'throw_original_catch_alias_2_warn' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_original_catch_alias_2_warn' here void try_nested_try(int n) noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions @@ -568,8 +539,7 @@ void bad_try_nested_try(int n) noexcept { } catch(double &) { } } -// CHECK-MESSAGES: :[[@LINE-11]]:6: note: throw stack of unhandled exception, starting from function 'bad_try_nested_try' -// CHECK-MESSAGES: :[[@LINE-9]]:12: note: frame #0: function 'bad_try_nested_try' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #0: unhandled exception may be thrown in function 'bad_try_nested_try' here void try_nested_catch() noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions @@ -607,8 +577,7 @@ void bad_catch_nested_try() noexcept { } catch(double &) { } } -// CHECK-MESSAGES: :[[@LINE-12]]:6: note: throw stack of unhandled exception, starting from function 'bad_catch_nested_try' -// CHECK-MESSAGES: :[[@LINE-7]]:7: note: frame #0: function 'bad_catch_nested_try' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-6]]:7: note: frame #0: unhandled exception may be thrown in function 'bad_catch_nested_try' here void implicit_int_thrower() { throw 1; @@ -622,17 +591,15 @@ void indirect_implicit() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions implicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'indirect_implicit' -// CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_implicit' -// CHECK-MESSAGES: :[[@LINE-13]]:3: note: frame #1: function 'implicit_int_thrower' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #0: unhandled exception may be thrown in function 'implicit_int_thrower' here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_implicit' calls function 'implicit_int_thrower' here void indirect_explicit() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions explicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'indirect_explicit' -// CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'indirect_explicit' -// CHECK-MESSAGES: :[[@LINE-17]]:3: note: frame #1: function 'explicit_int_thrower' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-14]]:3: note: frame #0: unhandled exception may be thrown in function 'explicit_int_thrower' here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_explicit' calls function 'explicit_int_thrower' here void indirect_catch() noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_catch' which should not throw exceptions @@ -653,22 +620,19 @@ void swap(int&, int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'swap' -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'swap' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'swap' here void iter_swap(int&, int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'iter_swap' -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'iter_swap' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'iter_swap' here void iter_move(int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'iter_move' -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'iter_move' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'iter_move' here namespace std { class bad_alloc {}; @@ -687,16 +651,14 @@ void enabled1() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'enabled1' -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: function 'enabled1' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'enabled1' here void enabled2() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions enabled1(); } -// CHECK-MESSAGES: :[[@LINE-4]]:6: note: throw stack of unhandled exception, starting from function 'enabled2' -// CHECK-MESSAGES: :[[@LINE-5]]:6: note: frame #0: function 'enabled2' -// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #1: function 'enabled1' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-8]]:3: note: frame #0: unhandled exception may be thrown in function 'enabled1' here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'enabled2' calls function 'enabled1' here void enabled3() { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled3' which should not throw exceptions @@ -728,8 +690,7 @@ void this_counts(int n) noexcept { if (n) throw 1; throw ignored1(); } -// CHECK-MESSAGES: :[[@LINE-5]]:6: note: throw stack of unhandled exception, starting from function 'this_counts' -// CHECK-MESSAGES: :[[@LINE-4]]:10: note: frame #0: function 'this_counts' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:10: note: frame #0: unhandled exception may be thrown in function 'this_counts' here void thrower(int n) { throw n; @@ -741,9 +702,8 @@ int directly_recursive(int n) noexcept { thrower(n); return directly_recursive(n); } -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: throw stack of unhandled exception, starting from function 'directly_recursive' -// CHECK-MESSAGES: :[[@LINE-7]]:5: note: frame #0: function 'directly_recursive' -// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #1: function 'thrower' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #0: unhandled exception may be thrown in function 'thrower' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #1: function 'directly_recursive' calls function 'thrower' here int indirectly_recursive(int n) noexcept; @@ -758,6 +718,8 @@ int indirectly_recursive(int n) noexcept { thrower(n); return recursion_helper(n); } +// CHECK-MESSAGES: :[[@LINE-25]]:3: note: frame #0: unhandled exception may be thrown in function 'thrower' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #1: function 'indirectly_recursive' calls function 'thrower' here struct super_throws { super_throws() noexcept(false) { throw 42; } @@ -767,9 +729,8 @@ struct sub_throws : super_throws { sub_throws() noexcept : super_throws() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'sub_throws' -// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'sub_throws' -// CHECK-MESSAGES: :[[@LINE-9]]:36: note: frame #1: function 'super_throws' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-7]]:36: note: frame #0: unhandled exception may be thrown in function 'super_throws' here +// CHECK-MESSAGES: :[[@LINE-4]]:27: note: frame #1: function 'sub_throws' calls function 'super_throws' here struct init_member_throws { super_throws s; @@ -777,8 +738,8 @@ struct init_member_throws { init_member_throws() noexcept : s() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'init_member_throws' -// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'init_member_throws' +// CHECK-MESSAGES: :[[@LINE-16]]:36: note: frame #0: unhandled exception may be thrown in function 'super_throws' here +// CHECK-MESSAGES: :[[@LINE-4]]:35: note: frame #1: function 'init_member_throws' calls function 'super_throws' here struct implicit_init_member_throws { super_throws s; @@ -786,8 +747,8 @@ struct implicit_init_member_throws { implicit_init_member_throws() noexcept {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'implicit_init_member_throws' -// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'implicit_init_member_throws' +// CHECK-MESSAGES: :[[@LINE-25]]:36: note: frame #0: unhandled exception may be thrown in function 'super_throws' here +// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #1: function 'implicit_init_member_throws' calls function 'super_throws' struct init { explicit init(int, int) noexcept(false) { throw 42; } @@ -799,25 +760,22 @@ struct in_class_init_throws { in_class_init_throws() noexcept {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: throw stack of unhandled exception, starting from function 'in_class_init_throws' -// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'in_class_init_throws' -// CHECK-MESSAGES: :[[@LINE-11]]:45: note: frame #1: function 'init' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-9]]:45: note: frame #0: unhandled exception may be thrown in function 'init' here +// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #1: function 'in_class_init_throws' calls function 'init' here int main() { // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'main' which should not throw exceptions throw 1; return 0; } -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: throw stack of unhandled exception, starting from function 'main' -// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #0: function 'main' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: unhandled exception may be thrown in function 'main' here // The following function all incorrectly throw exceptions, *but* calling them // should not yield a warning because they are marked as noexcept. void test_basic_no_throw() noexcept { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'test_basic_no_throw' which should not throw exceptions -// CHECK-MESSAGES: :[[@LINE-2]]:6: note: throw stack of unhandled exception, starting from function 'test_basic_no_throw' -// CHECK-MESSAGES: :[[@LINE-3]]:39: note: frame #0: function 'test_basic_no_throw' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-2]]:39: note: frame #0: unhandled exception may be thrown in function 'test_basic_no_throw' here void test_basic_throw() noexcept(false) { throw 42; } @@ -830,9 +788,8 @@ void calls_non_and_throwing() noexcept { test_basic_no_throw(); test_basic_throw(); } -// CHECK-MESSAGES: :[[@LINE-5]]:6: note: throw stack of unhandled exception, starting from function 'calls_non_and_throwing' -// CHECK-MESSAGES: :[[@LINE-6]]:6: note: frame #0: function 'calls_non_and_throwing' -// CHECK-MESSAGES: :[[@LINE-13]]:43: note: frame #1: function 'test_basic_throw' throws unhandled exception here +// CHECK-MESSAGES: :[[@LINE-11]]:43: note: frame #0: unhandled exception may be thrown in function 'test_basic_throw' here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'calls_non_and_throwing' calls function 'test_basic_throw' here namespace PR55143 { namespace PR40583 { @@ -850,17 +807,14 @@ struct test_implicit_throw { test_implicit_throw(const test_implicit_throw&) { throw 42; } test_implicit_throw(test_implicit_throw&&) { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'test_implicit_throw' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:5: note: throw stack of unhandled exception, starting from function 'test_implicit_throw' - // CHECK-MESSAGES: :[[@LINE-3]]:50: note: frame #0: function 'test_implicit_throw' + // CHECK-MESSAGES: :[[@LINE-2]]:50: note: frame #0: unhandled exception may be thrown in function 'test_implicit_throw' here test_implicit_throw& operator=(const test_implicit_throw&) { throw 42; } test_implicit_throw& operator=(test_implicit_throw&&) { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: an exception may be thrown in function 'operator=' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:26: note: throw stack of unhandled exception, starting from function 'operator=' - // CHECK-MESSAGES: :[[@LINE-3]]:61: note: frame #0: function 'operator=' + // CHECK-MESSAGES: :[[@LINE-2]]:61: note: frame #0: unhandled exception may be thrown in function 'operator=' ~test_implicit_throw() { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function '~test_implicit_throw' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:5: note: throw stack of unhandled exception, starting from function '~test_implicit_throw' - // CHECK-MESSAGES: :[[@LINE-3]]:30: note: frame #0: function '~test_implicit_throw' + // CHECK-MESSAGES: :[[@LINE-2]]:30: note: frame #0: unhandled exception may be thrown in function '~test_implicit_throw' here }; }} From 2e14a63004e659a9bdbc850050e731139035fdfc Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 18 Jun 2025 23:06:06 +0300 Subject: [PATCH 4/4] added types of throw exception and more tests --- .../bugprone/ExceptionEscapeCheck.cpp | 14 +- .../bugprone/exception-escape-coro.cpp | 84 ++++----- .../bugprone/exception-escape-rethrow.cpp | 4 +- .../bugprone/exception-escape-throw.cpp | 46 ++++- .../checkers/bugprone/exception-escape.cpp | 160 ++++++++++++------ 5 files changed, 201 insertions(+), 107 deletions(-) diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 012ed598b76cd..8eb7881a47a26 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -81,26 +81,24 @@ void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) { const utils::ExceptionAnalyzer::ExceptionInfo Info = Tracer.analyze(MatchedDecl); - if (Info.getBehaviour() != utils::ExceptionAnalyzer::State::Throwing) { + if (Info.getBehaviour() != utils::ExceptionAnalyzer::State::Throwing) return; - } diag(MatchedDecl->getLocation(), "an exception may be thrown in function " "%0 which should not throw exceptions") << MatchedDecl; - const utils::ExceptionAnalyzer::ExceptionInfo::ThrowInfo ThrowInfo = - Info.getExceptions().begin()->getSecond(); + const auto &[ThrowType, ThrowInfo] = *Info.getExceptions().begin(); - if (ThrowInfo.Loc.isInvalid()) { + if (ThrowInfo.Loc.isInvalid()) return; - } const utils::ExceptionAnalyzer::CallStack &Stack = ThrowInfo.Stack; diag(ThrowInfo.Loc, - "frame #0: unhandled exception may be thrown in function %0 here", + "frame #0: unhandled exception of type %0 may be thrown in function %1 " + "here", DiagnosticIDs::Note) - << Stack.back().first; + << QualType(ThrowType, 0U) << Stack.back().first; size_t FrameNo = 1; for (auto CurrIt = ++Stack.rbegin(), PrevIt = Stack.rbegin(); diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp index bf0a358353a9f..cd5f019ff9f6e 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-coro.cpp @@ -221,7 +221,7 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_return a / b; } -// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here // CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #1: function 'c_ShouldDiag' calls function '~Evil' Task d_ShouldNotDiag(const int a, const int b) { @@ -232,7 +232,7 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here // CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here // CHECK-MESSAGES: :[[@LINE-6]]:17: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here @@ -244,7 +244,7 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here // CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here Task f_ShouldNotDiag(const int a, const int b) { @@ -255,7 +255,7 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here // CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here Task g_ShouldNotDiag(const int a, const int b) { @@ -267,7 +267,7 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here // CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here Task h_ShouldNotDiag(const int a, @@ -280,7 +280,7 @@ Task h_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_return a / b; } -// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here // CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here Task @@ -309,7 +309,7 @@ j_ShouldDiag(const int a, const int b) noexcept { co_return a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'j_ShouldDiag' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'j_ShouldDiag' here } // namespace coreturn @@ -343,7 +343,7 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_yield a / b; } -// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here // CHECK-MESSAGES: :[[@LINE-8]]:11: note: frame #1: function 'c_ShouldDiag' calls function '~Evil' Task d_ShouldNotDiag(const int a, const int b) { @@ -354,7 +354,7 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here // CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here // CHECK-MESSAGES: :[[@LINE-6]]:17: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here @@ -366,7 +366,7 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here // CHECK-MESSAGES: :[[@LINE-5]]:24: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here Task f_ShouldNotDiag(const int a, const int b) { @@ -377,7 +377,7 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here // CHECK-MESSAGES: :[[@LINE-5]]:31: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here Task g_ShouldNotDiag(const int a, const int b) { @@ -389,7 +389,7 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:38: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here // CHECK-MESSAGES: :[[@LINE-6]]:38: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here Task h_ShouldNotDiag(const int a, @@ -402,7 +402,7 @@ Task h_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:45: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_yield a / b; } -// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here // CHECK-MESSAGES: :[[@LINE-6]]:45: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here Task @@ -431,7 +431,7 @@ j_ShouldDiag(const int a, const int b) noexcept { co_yield a / b; } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'j_ShouldDiag' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'j_ShouldDiag' here } // namespace coyield @@ -465,7 +465,7 @@ Task c_ShouldDiag(const int a, const int b) noexcept { co_await returnOne(); } -// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here // CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #1: function 'c_ShouldDiag' calls function '~Evil' Task d_ShouldNotDiag(const int a, const int b) { @@ -476,7 +476,7 @@ Task d_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: an exception may be thrown in function 'd_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :81:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :81:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here // CHECK-MESSAGES: :158:12: note: frame #1: function 'get_return_object' calls function 'Task' here // CHECK-MESSAGES: :[[@LINE-6]]:18: note: frame #2: function 'd_ShouldDiag' calls function 'get_return_object' here @@ -488,7 +488,7 @@ Task e_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: an exception may be thrown in function 'e_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :149:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :149:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here // CHECK-MESSAGES: :[[@LINE-5]]:25: note: frame #1: function 'e_ShouldDiag' calls function 'Promise' here Task f_ShouldNotDiag(const int a, const int b) { @@ -499,7 +499,7 @@ Task f_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: an exception may be thrown in function 'f_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :163:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :163:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here // CHECK-MESSAGES: :[[@LINE-5]]:32: note: frame #1: function 'f_ShouldDiag' calls function 'initial_suspend' here Task g_ShouldNotDiag(const int a, @@ -512,7 +512,7 @@ Task g_ShouldDiag(const int a, // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: an exception may be thrown in function 'g_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :155:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :155:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here // CHECK-MESSAGES: :[[@LINE-6]]:39: note: frame #1: function 'g_ShouldDiag' calls function 'get_return_object' here Task h_ShouldNotDiag(const int a, @@ -525,7 +525,7 @@ h_ShouldDiag(const int a, const int b) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: an exception may be thrown in function 'h_ShouldDiag' which should not throw exceptions co_await returnOne(); } -// CHECK-MESSAGES: :175:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :175:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here // CHECK-MESSAGES: :[[@LINE-5]]:1: note: frame #1: function 'h_ShouldDiag' calls function 'unhandled_exception' here Task @@ -552,7 +552,7 @@ j_ShouldDiag(const int a, const int b) noexcept { if (b == 0) throw b; } -// CHECK-MESSAGES: :[[@LINE-2]]:5: note: frame #0: unhandled exception may be thrown in function 'j_ShouldDiag' here +// CHECK-MESSAGES: :[[@LINE-2]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'j_ShouldDiag' here } // namespace coawait @@ -591,7 +591,7 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_return a / b; }; -// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here // CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil' const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -603,7 +603,7 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here // CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here // CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here @@ -617,7 +617,7 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here const auto f_ShouldNotDiag = [](const int a, @@ -630,7 +630,7 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here const auto g_ShouldNotDiag = @@ -644,7 +644,7 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here const auto h_ShouldNotDiag = @@ -659,7 +659,7 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_return a / b; }; -// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here const auto i_ShouldNotDiag = @@ -692,7 +692,7 @@ const auto j_ShouldDiag = co_return a / b; }; -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'operator()' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here } // namespace coreturn @@ -727,7 +727,7 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_yield a / b; }; -// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here // CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil' const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -739,7 +739,7 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :54:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here // CHECK-MESSAGES: :109:12: note: frame #1: function 'get_return_object' calls function 'Task' here // CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here @@ -753,7 +753,7 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :100:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here const auto f_ShouldNotDiag = [](const int a, @@ -766,7 +766,7 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :114:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here const auto g_ShouldNotDiag = @@ -780,7 +780,7 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :106:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here const auto h_ShouldNotDiag = @@ -795,7 +795,7 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_yield a / b; }; -// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :133:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here const auto i_ShouldNotDiag = @@ -828,7 +828,7 @@ const auto j_ShouldDiag = co_yield a / b; }; -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'operator()' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here } // namespace coyield @@ -863,7 +863,7 @@ const auto c_ShouldDiag = [](const int a, const int b) noexcept -> Task { co_await returnOne(); }; -// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception may be thrown in function '~Evil' here +// CHECK-MESSAGES: :186:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~Evil' here // CHECK-MESSAGES: :[[@LINE-8]]:27: note: frame #1: function 'operator()' calls function '~Evil' const auto d_ShouldNotDiag = [](const int a, const int b) -> Task { @@ -875,7 +875,7 @@ const auto d_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :81:7: note: frame #0: unhandled exception may be thrown in function 'Task' here +// CHECK-MESSAGES: :81:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Task' here // CHECK-MESSAGES: :158:12: note: frame #1: function 'get_return_object' calls function 'Task' here // CHECK-MESSAGES: :[[@LINE-7]]:27: note: frame #2: function 'operator()' calls function 'get_return_object' here @@ -889,7 +889,7 @@ const auto e_ShouldDiag = [](const int a, // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :149:7: note: frame #0: unhandled exception may be thrown in function 'Promise' here +// CHECK-MESSAGES: :149:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'Promise' here // CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #1: function 'operator()' calls function 'Promise' here const auto f_ShouldNotDiag = [](const int a, @@ -902,7 +902,7 @@ const auto f_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :163:7: note: frame #0: unhandled exception may be thrown in function 'initial_suspend' here +// CHECK-MESSAGES: :163:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'initial_suspend' here // CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #1: function 'operator()' calls function 'initial_suspend' here const auto g_ShouldNotDiag = @@ -916,7 +916,7 @@ const auto g_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :155:7: note: frame #0: unhandled exception may be thrown in function 'get_return_object' here +// CHECK-MESSAGES: :155:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'get_return_object' here // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'get_return_object' here const auto h_ShouldNotDiag = @@ -931,7 +931,7 @@ const auto h_ShouldDiag = // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: an exception may be thrown in function 'operator()' which should not throw exceptions co_await returnOne(); }; -// CHECK-MESSAGES: :175:7: note: frame #0: unhandled exception may be thrown in function 'unhandled_exception' here +// CHECK-MESSAGES: :175:7: note: frame #0: unhandled exception of type 'int' may be thrown in function 'unhandled_exception' here // CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #1: function 'operator()' calls function 'unhandled_exception' here const auto i_ShouldNotDiag = @@ -962,7 +962,7 @@ const auto j_ShouldDiag = if (b == 0) throw b; }; -// CHECK-MESSAGES: :[[@LINE-2]]:5: note: frame #0: unhandled exception may be thrown in function 'operator()' here +// CHECK-MESSAGES: :[[@LINE-2]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator()' here } // namespace coawait diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp index 7ac5aeb6428b6..b79ce30ac630c 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-rethrow.cpp @@ -22,7 +22,7 @@ int throwsAndCallsRethrower() noexcept { } return 1; } -// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #0: unhandled exception may be thrown in function 'throwsAndCallsRethrower' here +// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwsAndCallsRethrower' here int throwsAndCallsCallsRethrower() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'throwsAndCallsCallsRethrower' which should not throw exceptions @@ -33,7 +33,7 @@ int throwsAndCallsCallsRethrower() noexcept { } return 1; } -// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #0: unhandled exception may be thrown in function 'throwsAndCallsCallsRethrower' here +// CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwsAndCallsCallsRethrower' here void rethrowerNoexcept() noexcept { throw; diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp index dc29b6593243a..ba139937c0757 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape-throw.cpp @@ -4,7 +4,7 @@ void throwing_throw_nothing() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_throw_nothing' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'throwing_throw_nothing' here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwing_throw_nothing' here void explicit_int_thrower() throw(int); @@ -16,14 +16,14 @@ void indirect_implicit() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions implicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-7]]:3: note: frame #0: unhandled exception may be thrown in function 'implicit_int_thrower' here +// CHECK-MESSAGES: :[[@LINE-7]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'implicit_int_thrower' here // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_implicit' calls function 'implicit_int_thrower' here void indirect_explicit() throw() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions explicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-17]]:29: note: frame #0: unhandled exception may be thrown in function 'explicit_int_thrower' here +// CHECK-MESSAGES: :[[@LINE-17]]:29: note: frame #0: unhandled exception of type 'int' may be thrown in function 'explicit_int_thrower' here // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_explicit' calls function 'explicit_int_thrower' here struct super_throws { @@ -34,5 +34,43 @@ struct sub_throws : super_throws { sub_throws() throw() : super_throws() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-7]]:31: note: frame #0: unhandled exception may be thrown in function 'super_throws' here +// CHECK-MESSAGES: :[[@LINE-7]]:31: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here // CHECK-MESSAGES: :[[@LINE-4]]:26: note: frame #1: function 'sub_throws' calls function 'super_throws' here + +struct base_throwing_ctor { + base_throwing_ctor() throw(int) { throw 123; } +}; + +struct intermediate_ctor : base_throwing_ctor { + intermediate_ctor() throw(int) : base_throwing_ctor() {} +}; + +struct final_no_throw : intermediate_ctor { + final_no_throw() throw() : intermediate_ctor() {} + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'final_no_throw' which should not throw exceptions +}; +// CHECK-MESSAGES: :[[@LINE-11]]:37: note: frame #0: unhandled exception of type 'int' may be thrown in function 'base_throwing_ctor' here +// CHECK-MESSAGES: :[[@LINE-8]]:36: note: frame #1: function 'intermediate_ctor' calls function 'base_throwing_ctor' here +// CHECK-MESSAGES: :[[@LINE-5]]:30: note: frame #2: function 'final_no_throw' calls function 'intermediate_ctor' here + +// Member initializer with call stack +struct member_thrower { + member_thrower() throw(double) { throw 3.14; } +}; + +struct has_throwing_member { + member_thrower member; + has_throwing_member() throw() : member() {} + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'has_throwing_member' which should not throw exceptions +}; +// CHECK-MESSAGES: :[[@LINE-8]]:36: note: frame #0: unhandled exception of type 'double' may be thrown in function 'member_thrower' here +// CHECK-MESSAGES: :[[@LINE-4]]:35: note: frame #1: function 'has_throwing_member' calls function 'member_thrower' here + +void multi_spec_thrower() throw(int, double, const char*); + +void calls_multi_spec() throw() { +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'calls_multi_spec' which should not throw exceptions + multi_spec_thrower(); +} +// CHECK-MESSAGES: :[[@LINE-6]]:27: note: frame #0: unhandled exception of type '{{(int|double|const char \*)}}' may be thrown in function 'multi_spec_thrower' here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'calls_multi_spec' calls function 'multi_spec_thrower' here diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp index 4313b105a6430..b10bd1d482867 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/exception-escape.cpp @@ -12,7 +12,7 @@ struct throwing_destructor { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function '~throwing_destructor' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function '~throwing_destructor' here struct throwing_move_constructor { throwing_move_constructor(throwing_move_constructor&&) { @@ -20,7 +20,7 @@ struct throwing_move_constructor { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throwing_move_constructor' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwing_move_constructor' here struct throwing_move_assignment { throwing_move_assignment& operator=(throwing_move_assignment&&) { @@ -28,13 +28,13 @@ struct throwing_move_assignment { throw 1; } }; -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'operator=' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator=' here void throwing_noexcept() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throwing_noexcept' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'throwing_noexcept' here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throwing_noexcept' here void throw_and_catch() noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch' which should not throw exceptions @@ -52,7 +52,7 @@ void throw_and_catch_some(int n) noexcept { } catch(int &) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_and_catch_some' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'double' may be thrown in function 'throw_and_catch_some' here void throw_and_catch_each(int n) noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_and_catch_each' which should not throw exceptions @@ -81,7 +81,7 @@ void throw_and_rethrow() noexcept { throw; } } -// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_and_rethrow' here +// CHECK-MESSAGES: :[[@LINE-5]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_and_rethrow' here void throw_catch_throw() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_throw' which should not throw exceptions @@ -91,7 +91,7 @@ void throw_catch_throw() noexcept { throw 2; } } -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_catch_throw' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'int' may be thrown in function 'throw_catch_throw' here void throw_catch_rethrow_the_rest(int n) noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_catch_rethrow_the_rest' which should not throw exceptions @@ -103,7 +103,7 @@ void throw_catch_rethrow_the_rest(int n) noexcept { throw; } } -// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_catch_rethrow_the_rest' here +// CHECK-MESSAGES: :[[@LINE-6]]:5: note: frame #0: unhandled exception of type 'double' may be thrown in function 'throw_catch_rethrow_the_rest' here void throw_catch_pointer_c() noexcept { try { @@ -134,7 +134,7 @@ void throw_catch_multi_ptr_1() noexcept { } catch (const char **) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_catch_multi_ptr_1' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_catch_multi_ptr_1' here void throw_catch_multi_ptr_2() noexcept { try { @@ -180,7 +180,7 @@ void throw_c_catch_pointer() noexcept { throw p; } catch(int *) {} } -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_c_catch_pointer' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const int *' may be thrown in function 'throw_c_catch_pointer' here 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 @@ -190,7 +190,7 @@ void throw_c_catch_pointer_v() noexcept { throw p; } catch(volatile int *) {} } -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_c_catch_pointer_v' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const int *' may be thrown in function 'throw_c_catch_pointer_v' here 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 @@ -200,7 +200,7 @@ void throw_v_catch_pointer() noexcept { throw p; } catch(int *) {} } -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_v_catch_pointer' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'volatile int *' may be thrown in function 'throw_v_catch_pointer' here 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 @@ -210,7 +210,7 @@ void throw_v_catch_pointer_c() noexcept { throw p; } catch(const int *) {} } -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_v_catch_pointer_c' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'volatile int *' may be thrown in function 'throw_v_catch_pointer_c' here 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 @@ -220,7 +220,7 @@ void throw_cv_catch_pointer_c() noexcept { throw p; } catch(const int *) {} } -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_cv_catch_pointer_c' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const volatile int *' may be thrown in function 'throw_cv_catch_pointer_c' here 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 @@ -230,7 +230,7 @@ void throw_cv_catch_pointer_v() noexcept { throw p; } catch(volatile int *) {} } -// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_cv_catch_pointer_v' here +// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #0: unhandled exception of type 'const volatile int *' may be thrown in function 'throw_cv_catch_pointer_v' here class base {}; class derived: public base {}; @@ -278,7 +278,7 @@ void throw_derived_catch_base_ptr() noexcept { } catch(base *) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_ptr' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'const derived *' may be thrown in function 'throw_derived_catch_base_ptr' here class A {}; class B : A {}; @@ -302,7 +302,7 @@ void throw_derived_catch_base_private() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_private' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'B' may be thrown in function 'throw_derived_catch_base_private' here void throw_derived_catch_base_private_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_private_ptr' which should not throw exceptions @@ -312,7 +312,7 @@ void throw_derived_catch_base_private_ptr() noexcept { } catch(A *) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_private_ptr' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'B *' may be thrown in function 'throw_derived_catch_base_private_ptr' here void throw_derived_catch_base_protected() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected' which should not throw exceptions @@ -322,7 +322,7 @@ void throw_derived_catch_base_protected() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_protected' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'C' may be thrown in function 'throw_derived_catch_base_protected' here void throw_derived_catch_base_protected_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_protected_ptr' which should not throw exceptions @@ -332,7 +332,7 @@ void throw_derived_catch_base_protected_ptr() noexcept { } catch(A *) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_protected_ptr' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'C *' may be thrown in function 'throw_derived_catch_base_protected_ptr' here void throw_derived_catch_base_ambiguous() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous' which should not throw exceptions @@ -342,7 +342,7 @@ void throw_derived_catch_base_ambiguous() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_ambiguous' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'E' may be thrown in function 'throw_derived_catch_base_ambiguous' here void throw_derived_catch_base_ambiguous_ptr() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' which should not throw exceptions @@ -352,7 +352,7 @@ void throw_derived_catch_base_ambiguous_ptr() noexcept { } catch(A) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'E' may be thrown in function 'throw_derived_catch_base_ambiguous_ptr' here void throw_alias_catch_original() noexcept { using alias = int; @@ -374,7 +374,7 @@ void throw_alias_catch_original_warn() noexcept { } catch (int) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_alias_catch_original_warn' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'float' may be thrown in function 'throw_alias_catch_original_warn' here void throw_original_catch_alias() noexcept { using alias = char; @@ -396,7 +396,7 @@ void throw_original_catch_alias_warn() noexcept { } catch (volatile const alias *const *) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_original_catch_alias_warn' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_original_catch_alias_warn' here void throw_original_catch_alias_2() noexcept { using alias = const char *const; @@ -457,7 +457,7 @@ void throw_basefn_catch_derivedfn() noexcept { } catch(void(derivedMember::*)()) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_basefn_catch_derivedfn' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'void (baseMember::*)()' may be thrown in function 'throw_basefn_catch_derivedfn' here void throw_basefn_catch_basefn() noexcept { try { @@ -474,7 +474,7 @@ void throw_basem_catch_basem_throw() noexcept { } catch(const int* baseMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_basem_catch_basem_throw' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *baseMember::**' may be thrown in function 'throw_basem_catch_basem_throw' here void throw_basem_catch_basem() noexcept { try { @@ -492,7 +492,7 @@ void throw_basem_catch_derivedm() noexcept { } catch(const int* const derivedMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_basem_catch_derivedm' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *baseMember::**' may be thrown in function 'throw_basem_catch_derivedm' here void throw_derivedm_catch_basem() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_derivedm_catch_basem' which should not throw exceptions @@ -502,7 +502,7 @@ void throw_derivedm_catch_basem() noexcept { } catch(const int* const baseMember::* const *) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_derivedm_catch_basem' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'int *derivedMember::**' may be thrown in function 'throw_derivedm_catch_basem' here void throw_original_catch_alias_2_warn() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'throw_original_catch_alias_2_warn' which should not throw exceptions @@ -514,7 +514,7 @@ void throw_original_catch_alias_2_warn() noexcept { } catch (volatile alias *) { } } -// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception may be thrown in function 'throw_original_catch_alias_2_warn' here +// CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #0: unhandled exception of type 'char **' may be thrown in function 'throw_original_catch_alias_2_warn' here void try_nested_try(int n) noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_try' which should not throw exceptions @@ -539,7 +539,7 @@ void bad_try_nested_try(int n) noexcept { } catch(double &) { } } -// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #0: unhandled exception may be thrown in function 'bad_try_nested_try' here +// CHECK-MESSAGES: :[[@LINE-8]]:12: note: frame #0: unhandled exception of type 'int' may be thrown in function 'bad_try_nested_try' here void try_nested_catch() noexcept { // CHECK-MESSAGES-NOT: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'try_nested_catch' which should not throw exceptions @@ -577,7 +577,7 @@ void bad_catch_nested_try() noexcept { } catch(double &) { } } -// CHECK-MESSAGES: :[[@LINE-6]]:7: note: frame #0: unhandled exception may be thrown in function 'bad_catch_nested_try' here +// CHECK-MESSAGES: :[[@LINE-6]]:7: note: frame #0: unhandled exception of type 'double' may be thrown in function 'bad_catch_nested_try' here void implicit_int_thrower() { throw 1; @@ -591,14 +591,14 @@ void indirect_implicit() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_implicit' which should not throw exceptions implicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #0: unhandled exception may be thrown in function 'implicit_int_thrower' here +// CHECK-MESSAGES: :[[@LINE-11]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'implicit_int_thrower' here // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_implicit' calls function 'implicit_int_thrower' here void indirect_explicit() noexcept { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'indirect_explicit' which should not throw exceptions explicit_int_thrower(); } -// CHECK-MESSAGES: :[[@LINE-14]]:3: note: frame #0: unhandled exception may be thrown in function 'explicit_int_thrower' here +// CHECK-MESSAGES: :[[@LINE-14]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'explicit_int_thrower' here // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'indirect_explicit' calls function 'explicit_int_thrower' here void indirect_catch() noexcept { @@ -620,19 +620,19 @@ void swap(int&, int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'swap' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'swap' here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'swap' here void iter_swap(int&, int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_swap' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'iter_swap' here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'iter_swap' here void iter_move(int&) { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'iter_move' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'iter_move' here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'iter_move' here namespace std { class bad_alloc {}; @@ -651,13 +651,13 @@ void enabled1() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled1' which should not throw exceptions throw 1; } -// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception may be thrown in function 'enabled1' here +// CHECK-MESSAGES: :[[@LINE-2]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'enabled1' here void enabled2() { // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'enabled2' which should not throw exceptions enabled1(); } -// CHECK-MESSAGES: :[[@LINE-8]]:3: note: frame #0: unhandled exception may be thrown in function 'enabled1' here +// CHECK-MESSAGES: :[[@LINE-8]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'enabled1' here // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'enabled2' calls function 'enabled1' here void enabled3() { @@ -668,6 +668,64 @@ void enabled3() { } } +void deep_level3_thrower() { + throw 42; +} + +void deep_level2_caller() { + deep_level3_thrower(); +} + +void deep_level1_caller() { + deep_level2_caller(); +} + +void deep_stack_test() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'deep_stack_test' which should not throw exceptions + deep_level1_caller(); +} +// CHECK-MESSAGES: :[[@LINE-15]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'deep_level3_thrower' here +// CHECK-MESSAGES: :[[@LINE-12]]:3: note: frame #1: function 'deep_level2_caller' calls function 'deep_level3_thrower' here +// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #2: function 'deep_level1_caller' calls function 'deep_level2_caller' here +// CHECK-MESSAGES: :[[@LINE-5]]:3: note: frame #3: function 'deep_stack_test' calls function 'deep_level1_caller' here + +// Template function call stack +template +void template_thrower(T t) { + throw T{}; +} + +template +void template_caller(T t) { + template_thrower(t); +} + +void template_stack_test() noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'template_stack_test' which should not throw exceptions + template_caller('a'); +} +// CHECK-MESSAGES: :[[@LINE-12]]:3: note: frame #0: unhandled exception of type 'char' may be thrown in function 'template_thrower' here +// CHECK-MESSAGES: :[[@LINE-8]]:3: note: frame #1: function 'template_caller' calls function 'template_thrower' here +// CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #2: function 'template_stack_test' calls function 'template_caller' here + +// template function without instantiation is not warned +template +void template_function_stack_test(T t) noexcept { + template_thrower(t); +} + +void multiple_exception_types(int choice) noexcept { +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'multiple_exception_types' which should not throw exceptions + if (choice == 1) { + throw 42; + } else if (choice == 2) { + throw 3.14; + } else if (choice == 3) { + throw "string"; + } +} +// CHECK-MESSAGES: note: frame #0: unhandled exception of type '{{(int|double|const char \*)}}' may be thrown in function 'multiple_exception_types' here + class ignored1 {}; class ignored2 {}; @@ -690,7 +748,7 @@ void this_counts(int n) noexcept { if (n) throw 1; throw ignored1(); } -// CHECK-MESSAGES: :[[@LINE-3]]:10: note: frame #0: unhandled exception may be thrown in function 'this_counts' here +// CHECK-MESSAGES: :[[@LINE-3]]:10: note: frame #0: unhandled exception of type 'int' may be thrown in function 'this_counts' here void thrower(int n) { throw n; @@ -702,7 +760,7 @@ int directly_recursive(int n) noexcept { thrower(n); return directly_recursive(n); } -// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #0: unhandled exception may be thrown in function 'thrower' here +// CHECK-MESSAGES: :[[@LINE-9]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #1: function 'directly_recursive' calls function 'thrower' here int indirectly_recursive(int n) noexcept; @@ -718,7 +776,7 @@ int indirectly_recursive(int n) noexcept { thrower(n); return recursion_helper(n); } -// CHECK-MESSAGES: :[[@LINE-25]]:3: note: frame #0: unhandled exception may be thrown in function 'thrower' here +// CHECK-MESSAGES: :[[@LINE-25]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'thrower' here // CHECK-MESSAGES: :[[@LINE-4]]:5: note: frame #1: function 'indirectly_recursive' calls function 'thrower' here struct super_throws { @@ -729,7 +787,7 @@ struct sub_throws : super_throws { sub_throws() noexcept : super_throws() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'sub_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-7]]:36: note: frame #0: unhandled exception may be thrown in function 'super_throws' here +// CHECK-MESSAGES: :[[@LINE-7]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here // CHECK-MESSAGES: :[[@LINE-4]]:27: note: frame #1: function 'sub_throws' calls function 'super_throws' here struct init_member_throws { @@ -738,7 +796,7 @@ struct init_member_throws { init_member_throws() noexcept : s() {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'init_member_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-16]]:36: note: frame #0: unhandled exception may be thrown in function 'super_throws' here +// CHECK-MESSAGES: :[[@LINE-16]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here // CHECK-MESSAGES: :[[@LINE-4]]:35: note: frame #1: function 'init_member_throws' calls function 'super_throws' here struct implicit_init_member_throws { @@ -747,7 +805,7 @@ struct implicit_init_member_throws { implicit_init_member_throws() noexcept {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'implicit_init_member_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-25]]:36: note: frame #0: unhandled exception may be thrown in function 'super_throws' here +// CHECK-MESSAGES: :[[@LINE-25]]:36: note: frame #0: unhandled exception of type 'int' may be thrown in function 'super_throws' here // CHECK-MESSAGES: :[[@LINE-4]]:3: note: frame #1: function 'implicit_init_member_throws' calls function 'super_throws' struct init { @@ -760,7 +818,7 @@ struct in_class_init_throws { in_class_init_throws() noexcept {} // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: an exception may be thrown in function 'in_class_init_throws' which should not throw exceptions }; -// CHECK-MESSAGES: :[[@LINE-9]]:45: note: frame #0: unhandled exception may be thrown in function 'init' here +// CHECK-MESSAGES: :[[@LINE-9]]:45: note: frame #0: unhandled exception of type 'int' may be thrown in function 'init' here // CHECK-MESSAGES: :[[@LINE-6]]:9: note: frame #1: function 'in_class_init_throws' calls function 'init' here int main() { @@ -768,14 +826,14 @@ int main() { throw 1; return 0; } -// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: unhandled exception may be thrown in function 'main' here +// CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #0: unhandled exception of type 'int' may be thrown in function 'main' here // The following function all incorrectly throw exceptions, *but* calling them // should not yield a warning because they are marked as noexcept. void test_basic_no_throw() noexcept { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in function 'test_basic_no_throw' which should not throw exceptions -// CHECK-MESSAGES: :[[@LINE-2]]:39: note: frame #0: unhandled exception may be thrown in function 'test_basic_no_throw' here +// CHECK-MESSAGES: :[[@LINE-2]]:39: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_basic_no_throw' here void test_basic_throw() noexcept(false) { throw 42; } @@ -788,7 +846,7 @@ void calls_non_and_throwing() noexcept { test_basic_no_throw(); test_basic_throw(); } -// CHECK-MESSAGES: :[[@LINE-11]]:43: note: frame #0: unhandled exception may be thrown in function 'test_basic_throw' here +// CHECK-MESSAGES: :[[@LINE-11]]:43: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_basic_throw' here // CHECK-MESSAGES: :[[@LINE-3]]:3: note: frame #1: function 'calls_non_and_throwing' calls function 'test_basic_throw' here namespace PR55143 { namespace PR40583 { @@ -807,14 +865,14 @@ struct test_implicit_throw { test_implicit_throw(const test_implicit_throw&) { throw 42; } test_implicit_throw(test_implicit_throw&&) { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function 'test_implicit_throw' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:50: note: frame #0: unhandled exception may be thrown in function 'test_implicit_throw' here + // CHECK-MESSAGES: :[[@LINE-2]]:50: note: frame #0: unhandled exception of type 'int' may be thrown in function 'test_implicit_throw' here test_implicit_throw& operator=(const test_implicit_throw&) { throw 42; } test_implicit_throw& operator=(test_implicit_throw&&) { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: an exception may be thrown in function 'operator=' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:61: note: frame #0: unhandled exception may be thrown in function 'operator=' + // CHECK-MESSAGES: :[[@LINE-2]]:61: note: frame #0: unhandled exception of type 'int' may be thrown in function 'operator=' ~test_implicit_throw() { throw 42; } // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: an exception may be thrown in function '~test_implicit_throw' which should not throw exceptions - // CHECK-MESSAGES: :[[@LINE-2]]:30: note: frame #0: unhandled exception may be thrown in function '~test_implicit_throw' here + // CHECK-MESSAGES: :[[@LINE-2]]:30: note: frame #0: unhandled exception of type 'int' may be thrown in function '~test_implicit_throw' here }; }}