llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tidy

Author: Julia Hansbrough (flowerhack)

<details>
<summary>Changes</summary>

See documentation for purpose and further details.

---
Full diff: https://github.com/llvm/llvm-project/pull/152970.diff


6 Files Affected:

- (modified) clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp (+3) 
- (modified) clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt (+1) 
- (added) 
clang-tools-extra/clang-tidy/bugprone/SuspiciousCopyInRangeLoopCheck.cpp (+44) 
- (added) 
clang-tools-extra/clang-tidy/bugprone/SuspiciousCopyInRangeLoopCheck.h (+34) 
- (added) 
clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-copy-in-range-loop.rst
 (+31) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-copy-in-range-loop.cpp
 (+7) 


``````````diff
diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp 
b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
index 824ebdfbd00dc..1e08d9b0ec977 100644
--- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -73,6 +73,7 @@
 #include "StringIntegerAssignmentCheck.h"
 #include "StringLiteralWithEmbeddedNulCheck.h"
 #include "StringviewNullptrCheck.h"
+#include "SuspiciousCopyInRangeLoopCheck.h"
 #include "SuspiciousEnumUsageCheck.h"
 #include "SuspiciousIncludeCheck.h"
 #include "SuspiciousMemoryComparisonCheck.h"
@@ -153,6 +154,8 @@ class BugproneModule : public ClangTidyModule {
         "bugprone-incorrect-enable-if");
     CheckFactories.registerCheck<IncorrectEnableSharedFromThisCheck>(
         "bugprone-incorrect-enable-shared-from-this");
+    CheckFactories.registerCheck<SuspiciousCopyInRangeLoopCheck>(
+        "bugprone-suspicious-copy-in-range-loop");
     CheckFactories.registerCheck<UnintendedCharOstreamOutputCheck>(
         "bugprone-unintended-char-ostream-output");
     CheckFactories.registerCheck<ReturnConstRefFromParameterCheck>(
diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
index 59928e5e47a09..c1835b5e4f82b 100644
--- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt
@@ -33,6 +33,7 @@ add_clang_library(clangTidyBugproneModule STATIC
   InvalidEnumDefaultInitializationCheck.cpp
   UnintendedCharOstreamOutputCheck.cpp
   ReturnConstRefFromParameterCheck.cpp
+  SuspiciousCopyInRangeLoopCheck.cpp
   SuspiciousStringviewDataUsageCheck.cpp
   SwitchMissingDefaultCaseCheck.cpp
   IncDecInConditionsCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/SuspiciousCopyInRangeLoopCheck.cpp 
b/clang-tools-extra/clang-tidy/bugprone/SuspiciousCopyInRangeLoopCheck.cpp
new file mode 100644
index 0000000000000..9f93a6bc2aeb0
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousCopyInRangeLoopCheck.cpp
@@ -0,0 +1,44 @@
+//===--- suspiciousCopyInRangeLoopCheck.cpp - clang-tidy
+//-------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SuspiciousCopyInRangeLoopCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::bugprone {
+
+// TODO: Possibly rename to "SuspiciousAutoCopyInRangeLoop"
+void SuspiciousCopyInRangeLoopCheck::registerMatchers(MatchFinder *Finder) {
+  // TODO: make sure this catches `const auto` as well.
+  auto auto_copy_in_range_based_for_loops =
+      cxxForRangeStmt(hasLoopVariable(varDecl(hasType(autoType()))));
+  Finder->addMatcher(auto_copy_in_range_based_for_loops.bind("for_range"),
+                     this);
+}
+
+void SuspiciousCopyInRangeLoopCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl =
+      Result.Nodes.getNodeAs<CXXForRangeStmt>("for_range");
+  std::string VarName = MatchedDecl->getLoopVariable()->getNameAsString();
+  if (MatchedDecl) {
+    diag(MatchedDecl->getBeginLoc(),
+         "Found potentially-spurious copy in range loop:\n* It is unlikely you 
"
+         "intended to copy '%0' for each iteration of the loop\n* To avoid "
+         "copying, use `auto&`\n* If this copy was intentional, do not use "
+         "`auto` and instead spell out the type explicitly")
+        << VarName
+        << FixItHint::CreateInsertion(
+               MatchedDecl->getLoopVariable()->getLocation(),
+               "suspicious copy here");
+  }
+}
+
+} // namespace clang::tidy::bugprone
diff --git 
a/clang-tools-extra/clang-tidy/bugprone/SuspiciousCopyInRangeLoopCheck.h 
b/clang-tools-extra/clang-tidy/bugprone/SuspiciousCopyInRangeLoopCheck.h
new file mode 100644
index 0000000000000..fe8c7bad76ae0
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousCopyInRangeLoopCheck.h
@@ -0,0 +1,34 @@
+//===--- SuspiciousCopyInRangeLoopCheck.h - clang-tidy -----------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSCOPYINRANGELOOPCHECK_H
+#define 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSCOPYINRANGELOOPCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::bugprone {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// 
http://clang.llvm.org/extra/clang-tidy/checks/bugprone/supsicious-copy-in-range-loop.html
+class SuspiciousCopyInRangeLoopCheck : public ClangTidyCheck {
+public:
+  SuspiciousCopyInRangeLoopCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus;
+  }
+};
+
+} // namespace clang::tidy::bugprone
+
+#endif // 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSCOPYINRANGELOOPCHECK_H
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-copy-in-range-loop.rst
 
b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-copy-in-range-loop.rst
new file mode 100644
index 0000000000000..6add3192fb7fa
--- /dev/null
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/bugprone/suspicious-copy-in-range-loop.rst
@@ -0,0 +1,31 @@
+.. title:: clang-tidy - bugprone-suspicious-copy-in-range-loop
+
+bugprone-suspicious-copy-in-range-loop
+================================
+
+This check finds ``for`` loops that are potentially-unintentionally copying
+the loop variable unnecessarily.
+
+For instance, this check would warn on a loop of the form:
+
+```for (auto s : strings) {
+    ...
+}
+```
+
+This can lead to bugs when the programmer operates on `s` in the loop, assuming
+they are mutating the elements directly, but they are in fact only mutating a
+temporary copy.
+
+In cases where the programmer's intention is to in fact copy the variable,
+the warning can be suppressed by explicitly stating the type.
+For instance, this check will *not* warn on a loop of the form
+
+```for (std::string s : strings) {
+ ...
+ }
+ ```
+
+This check is different from `performance-for-range-copy` in that
+it triggers on *every* instance where this pattern occurs rather than
+potentially-expensive ones.
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-copy-in-range-loop.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-copy-in-range-loop.cpp
new file mode 100644
index 0000000000000..3316c28e06f88
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/bugprone/suspicious-copy-in-range-loop.cpp
@@ -0,0 +1,7 @@
+// RUN: %check_clang_tidy %s bugprone-suspicious-copy-in-range-loop %t
+
+std::vector<std::string> some_strings;
+for (auto x : some_strings) {
+       std::cout << x << "\n";
+}
+// CHECK-MESSAGES: foo

``````````

</details>


https://github.com/llvm/llvm-project/pull/152970
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to