https://github.com/localspook updated 
https://github.com/llvm/llvm-project/pull/165955

>From 47c2c2ef1a65ffc55ef8a8a926fab39cc56a1429 Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <[email protected]>
Date: Fri, 31 Oct 2025 19:15:34 -0700
Subject: [PATCH 1/2] [clang-tidy] Fix `bugprone-exception-escape` not
 diagnosing throws in argument lists

---
 .../clang-tidy/utils/ExceptionAnalyzer.cpp    | 22 ++++++-----
 clang-tools-extra/docs/ReleaseNotes.rst       |  4 +-
 .../checkers/bugprone/exception-escape.cpp    | 39 ++++++++++++++++++-
 3 files changed, 53 insertions(+), 12 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp 
b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index fd4320eb8144b..db55d9f50e1bb 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -563,16 +563,6 @@ ExceptionAnalyzer::throwsException(const Stmt *St,
       }
     }
     Results.merge(Uncaught);
-  } else if (const auto *Call = dyn_cast<CallExpr>(St)) {
-    if (const FunctionDecl *Func = Call->getDirectCallee()) {
-      ExceptionInfo Excs =
-          throwsException(Func, Caught, CallStack, Call->getBeginLoc());
-      Results.merge(Excs);
-    }
-  } else if (const auto *Construct = dyn_cast<CXXConstructExpr>(St)) {
-    ExceptionInfo Excs = throwsException(Construct->getConstructor(), Caught,
-                                         CallStack, Construct->getBeginLoc());
-    Results.merge(Excs);
   } else if (const auto *DefaultInit = dyn_cast<CXXDefaultInitExpr>(St)) {
     ExceptionInfo Excs =
         throwsException(DefaultInit->getExpr(), Caught, CallStack);
@@ -605,6 +595,18 @@ ExceptionAnalyzer::throwsException(const Stmt *St,
       ExceptionInfo Excs = throwsException(Child, Caught, CallStack);
       Results.merge(Excs);
     }
+
+    if (const auto *Call = dyn_cast<CallExpr>(St)) {
+      if (const FunctionDecl *Func = Call->getDirectCallee()) {
+        ExceptionInfo Excs =
+            throwsException(Func, Caught, CallStack, Call->getBeginLoc());
+        Results.merge(Excs);
+      }
+    } else if (const auto *Construct = dyn_cast<CXXConstructExpr>(St)) {
+      ExceptionInfo Excs = throwsException(Construct->getConstructor(), Caught,
+                                           CallStack, 
Construct->getBeginLoc());
+      Results.merge(Excs);
+    }
   }
   return Results;
 }
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 33cc401bcb78f..76961e1efd945 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -260,7 +260,9 @@ Changes in existing checks
 - Improved :doc:`bugprone-exception-escape
   <clang-tidy/checks/bugprone/exception-escape>` check's handling of lambdas:
   exceptions from captures are now diagnosed, exceptions in the bodies of
-  lambdas that aren't actually invoked are not.
+  lambdas that aren't actually invoked are not. Additionally, fixed an issue
+  where the check wouldn't diagnose throws in arguments to functions or
+  constructors.
 
 - Improved :doc:`bugprone-infinite-loop
   <clang-tidy/checks/bugprone/infinite-loop>` check by adding detection for
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 a52bbe2246d1e..b7af7d81a3a7b 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
@@ -948,7 +948,7 @@ const auto throw_in_noexcept_lambda = [] () noexcept { 
throw 42; };
 // CHECK-MESSAGES: :[[@LINE-1]]:39: warning: an exception may be thrown in 
function 'operator()' which should not throw exceptions
 // CHECK-MESSAGES: :[[@LINE-2]]:56: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'operator()' here
 
-void thrower() {
+int thrower() {
   throw 42;
 }
 
@@ -956,3 +956,40 @@ const auto indirect_throw_in_noexcept_lambda = [] () 
noexcept { thrower(); };
 // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: an exception may be thrown in 
function 'operator()' which should not throw exceptions
 // CHECK-MESSAGES: :[[@LINE-5]]:3: note: frame #0: unhandled exception of type 
'int' may be thrown in function 'thrower' here
 // CHECK-MESSAGES: :[[@LINE-3]]:65: note: frame #1: function 'operator()' 
calls function 'thrower' here
+
+int f(int);
+void throw_in_function_arg() noexcept {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'throw_in_function_arg' which should not throw exceptions
+  f(false ? 0 : throw 1);
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:17: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'throw_in_function_arg' here
+
+void indirect_throw_in_function_arg() noexcept {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'indirect_throw_in_function_arg' which should not throw exceptions
+  f(thrower());
+}
+// CHECK-MESSAGES: :[[@LINE-19]]:3: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'thrower' here
+// CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #1: function 
'indirect_throw_in_function_arg' calls function 'thrower' here
+
+struct S {
+  S(int) noexcept {}
+};
+
+void throw_in_constructor_arg() noexcept {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'throw_in_constructor_arg' which should not throw exceptions
+  S s(false ? 0 : throw 1);
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:19: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'throw_in_constructor_arg' here
+
+void indirect_throw_in_constructor_arg() noexcept {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'indirect_throw_in_constructor_arg' which should not throw exceptions
+  S s = thrower();
+}
+// CHECK-MESSAGES: :[[@LINE-36]]:3: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'thrower' here
+// CHECK-MESSAGES: :[[@LINE-3]]:9: note: frame #1: function 
'indirect_throw_in_constructor_arg' calls function 'thrower' here
+
+void weird_throw_in_call_subexpression() noexcept {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'weird_throw_in_call_subexpression' which should not throw exceptions
+  (false ? []{} : throw 1)();
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:19: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'weird_throw_in_call_subexpression' here

>From f18becd273e9e57dcd68322b1a3d8c292c7d7f42 Mon Sep 17 00:00:00 2001
From: Victor Chernyakin <[email protected]>
Date: Tue, 4 Nov 2025 03:04:01 -0800
Subject: [PATCH 2/2] Add some more tests and comments

---
 .../clang-tidy/utils/ExceptionAnalyzer.cpp     |  3 +++
 .../checkers/bugprone/exception-escape.cpp     | 18 ++++++++++++++++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp 
b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
index db55d9f50e1bb..0e699e9d00aeb 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionAnalyzer.cpp
@@ -591,11 +591,14 @@ ExceptionAnalyzer::throwsException(const Stmt *St,
       Results.merge(Excs);
     }
   } else {
+    // Check whether any of this node's subexpressions throws.
     for (const Stmt *Child : St->children()) {
       ExceptionInfo Excs = throwsException(Child, Caught, CallStack);
       Results.merge(Excs);
     }
 
+    // If this node is a call to a function or constructor, also check
+    // whether the call itself throws.
     if (const auto *Call = dyn_cast<CallExpr>(St)) {
       if (const FunctionDecl *Func = Call->getDirectCallee()) {
         ExceptionInfo Excs =
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 b7af7d81a3a7b..140c93f5c2536 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
@@ -964,13 +964,27 @@ void throw_in_function_arg() noexcept {
 }
 // CHECK-MESSAGES: :[[@LINE-2]]:17: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'throw_in_function_arg' here
 
+int g(int, int, int);
+void throw_in_last_function_arg() noexcept {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'throw_in_last_function_arg' which should not throw exceptions
+  g(42, 67, false ? 0 : throw 1);
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:25: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'throw_in_last_function_arg' here
+
 void indirect_throw_in_function_arg() noexcept {
 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'indirect_throw_in_function_arg' which should not throw exceptions
   f(thrower());
 }
-// CHECK-MESSAGES: :[[@LINE-19]]:3: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'thrower' here
+// CHECK-MESSAGES: :[[@LINE-26]]:3: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'thrower' here
 // CHECK-MESSAGES: :[[@LINE-3]]:5: note: frame #1: function 
'indirect_throw_in_function_arg' calls function 'thrower' here
 
+void indirect_throw_from_lambda_in_function_arg() noexcept {
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'indirect_throw_from_lambda_in_function_arg' which should not throw 
exceptions
+  f([] { throw 1; return 0; }());
+}
+// CHECK-MESSAGES: :[[@LINE-2]]:10: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'operator()' here
+// CHECK-MESSAGES: :[[@LINE-3]]:30: note: frame #1: function 
'indirect_throw_from_lambda_in_function_arg' calls function 'operator()' here
+
 struct S {
   S(int) noexcept {}
 };
@@ -985,7 +999,7 @@ void indirect_throw_in_constructor_arg() noexcept {
 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: an exception may be thrown in 
function 'indirect_throw_in_constructor_arg' which should not throw exceptions
   S s = thrower();
 }
-// CHECK-MESSAGES: :[[@LINE-36]]:3: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'thrower' here
+// CHECK-MESSAGES: :[[@LINE-50]]:3: note: frame #0: unhandled exception of 
type 'int' may be thrown in function 'thrower' here
 // CHECK-MESSAGES: :[[@LINE-3]]:9: note: frame #1: function 
'indirect_throw_in_constructor_arg' calls function 'thrower' here
 
 void weird_throw_in_call_subexpression() noexcept {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to