[clang-tools-extra] [clang-tidy] Add recursion protection in ExceptionSpecAnalyzer (PR #66810)

Piotr Zegar via cfe-commits cfe-commits at lists.llvm.org
Wed Feb 12 21:57:19 PST 2025


https://github.com/PiotrZSL updated https://github.com/llvm/llvm-project/pull/66810

>From 4c4234a2c4c3e7a164befe5c89361f89ebd9728d Mon Sep 17 00:00:00 2001
From: Piotr Zegar <me at piotrzegar.pl>
Date: Tue, 19 Sep 2023 19:05:00 +0000
Subject: [PATCH] [clang-tidy] Add recursion protection in
 ExceptionSpecAnalyzer

Normally endless recursion should not happen in ExceptionSpecAnalyzer,
but if AST would be malformed (missing include), this could cause crash.

Fixes: #111436
---
 .../clang-tidy/utils/ExceptionSpecAnalyzer.cpp  | 13 +++++++------
 .../performance/noexcept-move-constructor.cpp   | 17 +++++++++++++++++
 2 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
index 4a9426ee7e8bb..0637d0eff688c 100644
--- a/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
+++ b/clang-tools-extra/clang-tidy/utils/ExceptionSpecAnalyzer.cpp
@@ -14,13 +14,14 @@ namespace clang::tidy::utils {
 
 ExceptionSpecAnalyzer::State
 ExceptionSpecAnalyzer::analyze(const FunctionDecl *FuncDecl) {
-  // Check if the function has already been analyzed and reuse that result.
-  const auto CacheEntry = FunctionCache.find(FuncDecl);
-  if (CacheEntry == FunctionCache.end()) {
+  // Check if function exist in cache or add temporary value to cache to protect
+  // against endless recursion.
+  const auto [CacheEntry, NotFound] =
+      FunctionCache.try_emplace(FuncDecl, State::NotThrowing);
+  if (NotFound) {
     ExceptionSpecAnalyzer::State State = analyzeImpl(FuncDecl);
-
-    // Cache the result of the analysis.
-    FunctionCache.try_emplace(FuncDecl, State);
+    // Update result with calculated value
+    FunctionCache[FuncDecl] = State;
     return State;
   }
 
diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp
index 347a1e3220061..4df0927b62af5 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance/noexcept-move-constructor.cpp
@@ -1,4 +1,6 @@
 // RUN: %check_clang_tidy %s performance-noexcept-move-constructor %t -- -- -fexceptions
+// RUN: %check_clang_tidy -std=c++17 -check-suffixes=,ERR %s performance-noexcept-move-constructor %t \
+// RUN:                   -- --fix-errors -- -fexceptions -DENABLE_ERROR
 
 namespace std
 {
@@ -397,3 +399,18 @@ namespace gh68101
       Container(Container&&) noexcept(std::is_nothrow_move_constructible<T>::value);
   };
 } // namespace gh68101
+
+namespace gh111436
+{
+
+template <typename value_type> class set {
+  set(set &&) = default;
+
+#ifdef ENABLE_ERROR
+  set(initializer_list<value_type> __l) {};
+  // CHECK-MESSAGES-ERR: :[[@LINE-1]]:7: error: member 'initializer_list' cannot have template arguments [clang-diagnostic-error]
+  // CHECK-MESSAGES-ERR: :[[@LINE-2]]:36: error: expected ')' [clang-diagnostic-error]
+#endif
+};
+
+} // namespace gh111436



More information about the cfe-commits mailing list