Repository navigation
[clang-tidy] Fix loop-convert for iterators with non-trivial destructors - #236084
yashaggarwal85d wants to merge 3 commits into
Conversation
|
Hello @yashaggarwal85d 👋 Thank you for submitting a Pull Request (PR) to the LLVM Project. Since this is your first PR, here are a few useful links covering our main contribution policies and review practices.
Please reply to this message to confirm that you have read these policies, especially the LLVM AI Tool Use Policy, and that any AI tool usage has been noted in the PR description. Frequently asked questionsHow do I add reviewers? This PR will be automatically labeled, and the relevant teams will be notified. For some parts of the project, reviewers may also be added automatically. You can also add reviewers manually using the Reviewers section on this page. If you cannot use that section, it is probably because you do not have write permissions for the repository. In that case, you can request a review by tagging reviewers in a comment using What if there are no comments? If you have not received any comments on your PR after a week, you can request a review by pinging the PR with a comment such as “Ping”. The common courtesy ping rate is once a week. Please remember that you are asking for volunteer time from other developers. Are any special GitHub settings required to contribute to LLVM? We only require contributors to have a public email address associated with their GitHub commits, see this section of LLVM Developer Policy for details. If you have questions, feel free to leave a comment on this PR, or ask on LLVM Discord or LLVM Discourse. Thank you, |
|
@llvm/pr-subscribers-clang-tools-extra Author: Yash Aggarwal (yashaggarwal85d) ChangesWhen the iterator type has a non-trivial destructor, the I added Fixes #234990 This was AI-assisted; I reviewed and tested the change myself. 3 Files Affected:
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;
+}
|
|
@llvm/pr-subscribers-clang-tidy Author: Yash Aggarwal (yashaggarwal85d) ChangesWhen the iterator type has a non-trivial destructor, the I added Fixes #234990 This was AI-assisted; I reviewed and tested the change myself. 3 Files Affected:
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;
+}
|
|
Read the policies, thanks |
|
|
zeyi2
left a comment
There was a problem hiding this comment.
Mostly LG! One comment for the tests.
Also please make your email address public :)
| @@ -0,0 +1,43 @@ | |||
| // RUN: %check_clang_tidy %s modernize-loop-convert %t | |||
There was a problem hiding this comment.
Could we move the test to existing loop-convert-extra.cpp?
There are also iterator and container types in Inputs/loop-convert/structures.h that we may be able to reuse or extend, rather than introducing a new Container here.
There was a problem hiding this comment.
Thanks! Moved the tests into loop-convert-extra.cpp and dropped the separate file.
Thanks @zeyi2 for the review. I have adressed them and made my email public as well. Thanks! |
A test run on llvm/llvm-project#236084 marked all 884 warnings TP with 873 "Same as #1" rationales and no reproducers, missing 4 real FPs. Require a source read per row, name the shared pattern in "Same as", and choose reproducer rows by pattern rather than by expected verdict. Amp-Thread-ID: https://ampcode.com/threads/T-01a19acc-7034-72fe-908f-15ca2649429a Co-authored-by: Zeyi Xu <[email protected]>
A run reviewing all 884 warnings of llvm/llvm-project#236084 hit the 45-minute step limit, which also skipped the second pass and the final report check. Raise the step limit to 120 minutes with per-pass timeouts so the check always runs, and have the agent save verdicts every 20 rows so a timeout keeps the finished rows. Amp-Thread-ID: https://ampcode.com/threads/T-01a19acc-7034-72fe-908f-15ca2649429a Co-authored-by: Zeyi Xu <[email protected]>
When the iterator type has a non-trivial destructor, the
end()call in the loop condition is wrapped in aCXXBindTemporaryExpr. The matcher for the loop bound only usedignoringParenImpCasts, which doesn't skip it, so loops likefor (It it = c.begin(); it != c.end(); ++it)were never flagged. This also hits MSVC STL iterators in debug builds (_ITERATOR_DEBUG_LEVEL=2).I added
ignoringImplicitinside it so the bound temporary is skipped too. The oldmaterializeTemporaryExpr(...)alternative is dropped becauseignoringParenImpCastsalready looks throughMaterializeTemporaryExpr, so it didn't match anything the first branch didn't.Fixes #234990
This was AI-assisted; I reviewed and tested the change myself.