https://github.com/yashaggarwal85d updated 
https://github.com/llvm/llvm-project/pull/236084

>From 81b3b4e3089077c0eef7d5792964294a89825361 Mon Sep 17 00:00:00 2001
From: Yash Aggarwal <[email protected]>
Date: Tue, 27 Oct 2026 11:20:17 +0000
Subject: [PATCH 1/2] [clang-tidy] Fix loop-convert for iterators with
 non-trivial destructors

---
 .../clang-tidy/modernize/LoopConvertCheck.cpp |  3 +-
 clang-tools-extra/docs/ReleaseNotes.md        |  5 +++
 .../loop-convert-nontrivial-iterator-dtor.cpp | 43 +++++++++++++++++++
 3 files changed, 49 insertions(+), 2 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-nontrivial-iterator-dtor.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
index 75bf2a73259000..d5b252b66522c3 100644
--- a/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/LoopConvertCheck.cpp
@@ -197,8 +197,7 @@ static StatementMatcher makeIteratorLoopMatcher(bool 
IsReverse) {
   const StatementMatcher IteratorBoundMatcher =
       expr(anyOf(ignoringParenImpCasts(
                      declRefExpr(to(varDecl(equalsBoundNode(EndVarName))))),
-                 ignoringParenImpCasts(expr(EndCallMatcher).bind(EndCallName)),
-                 materializeTemporaryExpr(ignoringParenImpCasts(
+                 ignoringParenImpCasts(ignoringImplicit(
                      expr(EndCallMatcher).bind(EndCallName)))));
 
   const StatementMatcher IteratorComparisonMatcher = 
expr(ignoringParenImpCasts(
diff --git a/clang-tools-extra/docs/ReleaseNotes.md 
b/clang-tools-extra/docs/ReleaseNotes.md
index 310b084c04eb04..45c5f30d05be7f 100644
--- a/clang-tools-extra/docs/ReleaseNotes.md
+++ b/clang-tools-extra/docs/ReleaseNotes.md
@@ -283,6 +283,11 @@ infrastructure are described first, followed by 
tool-specific sections.
   nested expressions involving different macros or a mix of macro and
   non-macro operands.
 
+- Improved {doc}`modernize-loop-convert
+  <clang-tidy/checks/modernize/loop-convert>` check to also convert iterator
+  loops that call `end()` in the condition when the iterator type has a
+  non-trivial destructor.
+
 - Fixed a crash in {doc}`modernize-raw-string-literal
   <clang-tidy/checks/modernize/raw-string-literal>` on synthetic string
   literals created for raw user-defined literal operators, such as `12_w`.
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-nontrivial-iterator-dtor.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-nontrivial-iterator-dtor.cpp
new file mode 100644
index 00000000000000..c19f21a59183c0
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-nontrivial-iterator-dtor.cpp
@@ -0,0 +1,43 @@
+// RUN: %check_clang_tidy %s modernize-loop-convert %t
+
+struct Container {
+  struct iterator {
+    ~iterator() {}
+    int &operator*() const;
+    iterator &operator++();
+    bool operator!=(const iterator &) const;
+  };
+  iterator begin();
+  iterator end();
+};
+
+void f(Container &C) {
+  for (Container::iterator It = C.begin(); It != C.end(); ++It)
+    (void)*It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : C)
+  // CHECK-FIXES-NEXT: (void)It;
+
+  for (Container::iterator It = C.begin(); It != (C.end()); ++It)
+    (void)*It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : C)
+  // CHECK-FIXES-NEXT: (void)It;
+
+  for (Container::iterator It = C.begin(); C.end() != It; ++It)
+    (void)*It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : C)
+  // CHECK-FIXES-NEXT: (void)It;
+
+  for (Container::iterator It = C.begin(), E = C.end(); It != E; ++It)
+    (void)*It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : C)
+  // CHECK-FIXES-NEXT: (void)It;
+}
+
+void negative(Container &C, Container &D) {
+  for (Container::iterator It = C.begin(); It != D.end(); ++It)
+    (void)*It;
+}

>From 7f067bd26789fd38ffb9507eae23a5cb6b099ace Mon Sep 17 00:00:00 2001
From: Yash Aggarwal <[email protected]>
Date: Mon, 2 Nov 2026 04:14:42 +0000
Subject: [PATCH 2/2] Move the non-trivial iterator destructor tests into
 loop-convert-extra.cpp

---
 .../Inputs/loop-convert/structures.h          | 12 ++++++
 .../checkers/modernize/loop-convert-extra.cpp | 33 ++++++++++++++
 .../loop-convert-nontrivial-iterator-dtor.cpp | 43 -------------------
 3 files changed, 45 insertions(+), 43 deletions(-)
 delete mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-nontrivial-iterator-dtor.cpp

diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
index 64ea452c0062f9..011a3b3e6e43f0 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/loop-convert/structures.h
@@ -252,6 +252,18 @@ struct RValueDerefContainer {
   iterator end() const;
 };
 
+template <typename T>
+struct NonTrivialDtorContainer {
+  struct iterator {
+    ~iterator();
+    bool operator!=(const iterator &other) const;
+    T &operator*();
+    iterator &operator++();
+  };
+  iterator begin();
+  iterator end();
+};
+
 namespace Macros {
 
 struct MacroStruct {
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-extra.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-extra.cpp
index 161427ca9ecb44..758dc7fc8f9750 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-extra.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-extra.cpp
@@ -1073,6 +1073,39 @@ void f() {
 
 } // namespace InitLists
 
+namespace NonTrivialIteratorDtor {
+
+void f(NonTrivialDtorContainer<int> &C, NonTrivialDtorContainer<int> &D) {
+  for (NonTrivialDtorContainer<int>::iterator It = C.begin(); It != C.end(); 
++It)
+    (void)*It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : C)
+  // CHECK-FIXES-NEXT: (void)It;
+
+  for (NonTrivialDtorContainer<int>::iterator It = C.begin(); It != (C.end()); 
++It)
+    (void)*It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : C)
+  // CHECK-FIXES-NEXT: (void)It;
+
+  for (NonTrivialDtorContainer<int>::iterator It = C.begin(); C.end() != It; 
++It)
+    (void)*It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : C)
+  // CHECK-FIXES-NEXT: (void)It;
+
+  for (NonTrivialDtorContainer<int>::iterator It = C.begin(), E = C.end(); It 
!= E; ++It)
+    (void)*It;
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
+  // CHECK-FIXES: for (int & It : C)
+  // CHECK-FIXES-NEXT: (void)It;
+
+  for (NonTrivialDtorContainer<int>::iterator It = C.begin(); It != D.end(); 
++It)
+    (void)*It;
+}
+
+} // namespace NonTrivialIteratorDtor
+
 void bug28341() {
   char v[5];
   for(int i = 0; i < 5; ++i) {
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-nontrivial-iterator-dtor.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-nontrivial-iterator-dtor.cpp
deleted file mode 100644
index c19f21a59183c0..00000000000000
--- 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/loop-convert-nontrivial-iterator-dtor.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-// RUN: %check_clang_tidy %s modernize-loop-convert %t
-
-struct Container {
-  struct iterator {
-    ~iterator() {}
-    int &operator*() const;
-    iterator &operator++();
-    bool operator!=(const iterator &) const;
-  };
-  iterator begin();
-  iterator end();
-};
-
-void f(Container &C) {
-  for (Container::iterator It = C.begin(); It != C.end(); ++It)
-    (void)*It;
-  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (int & It : C)
-  // CHECK-FIXES-NEXT: (void)It;
-
-  for (Container::iterator It = C.begin(); It != (C.end()); ++It)
-    (void)*It;
-  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (int & It : C)
-  // CHECK-FIXES-NEXT: (void)It;
-
-  for (Container::iterator It = C.begin(); C.end() != It; ++It)
-    (void)*It;
-  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (int & It : C)
-  // CHECK-FIXES-NEXT: (void)It;
-
-  for (Container::iterator It = C.begin(), E = C.end(); It != E; ++It)
-    (void)*It;
-  // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: use range-based for loop instead
-  // CHECK-FIXES: for (int & It : C)
-  // CHECK-FIXES-NEXT: (void)It;
-}
-
-void negative(Container &C, Container &D) {
-  for (Container::iterator It = C.begin(); It != D.end(); ++It)
-    (void)*It;
-}

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

Reply via email to