DNS320 created this revision.
DNS320 added reviewers: aaron.ballman, njames93, alexfh.
DNS320 added a project: clang-tools-extra.
Herald added subscribers: shchenz, kbarton, xazax.hun, mgorny, nemanjai.
DNS320 requested review of this revision.

This check implements the ES.74 
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Res-for-init> 
rule of the C++ Core Guidelines.

The goal of this check is to find for-statements which do not declare their 
loop variable in the initializer part.
This limits the loop variables visibility to the scope of the loop and prevents 
using the loop variable for other purposes after the loop.

Thank you for the review.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100092

Files:
  clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
  clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareLoopVariableInTheInitializerCheck.cpp
  
clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareLoopVariableInTheInitializerCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-declare-loop-variable-in-the-initializer.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-declare-loop-variable-in-the-initializer.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-declare-loop-variable-in-the-initializer.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines-declare-loop-variable-in-the-initializer.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s cppcoreguidelines-declare-loop-variable-in-the-initializer %t
+
+void forLoopFunction() {
+  const int Limit{10};
+  int I{0};
+
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: Prefer to declare a loop variable in the initializer part of a for-statement [cppcoreguidelines-declare-loop-variable-in-the-initializer]
+  for (; I < Limit; I++) {
+  }
+
+  // CHECK-MESSAGES: :[[@LINE+1]]:3: warning: Prefer to declare a loop variable in the initializer part of a for-statement [cppcoreguidelines-declare-loop-variable-in-the-initializer]
+  for (I = 0; I < Limit; I++) {
+  }
+
+  for (int I{0}; I < Limit; I++) { // OK
+  }
+}
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -143,6 +143,7 @@
    `concurrency-thread-canceltype-asynchronous <concurrency-thread-canceltype-asynchronous.html>`_,
    `cppcoreguidelines-avoid-goto <cppcoreguidelines-avoid-goto.html>`_,
    `cppcoreguidelines-avoid-non-const-global-variables <cppcoreguidelines-avoid-non-const-global-variables.html>`_,
+   `cppcoreguidelines-declare-loop-variable-in-the-initializer <cppcoreguidelines-declare-loop-variable-in-the-initializer.html>`_,
    `cppcoreguidelines-init-variables <cppcoreguidelines-init-variables.html>`_, "Yes"
    `cppcoreguidelines-interfaces-global-init <cppcoreguidelines-interfaces-global-init.html>`_,
    `cppcoreguidelines-macro-usage <cppcoreguidelines-macro-usage.html>`_,
Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-declare-loop-variable-in-the-initializer.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-declare-loop-variable-in-the-initializer.rst
@@ -0,0 +1,33 @@
+.. title:: clang-tidy - cppcoreguidelines-declare-loop-variable-in-the-initializer
+
+cppcoreguidelines-declare-loop-variable-in-the-initializer
+==========================================================
+
+Checks if a loop variable is declared in the initializer part of a for-statement.
+
+This check implements the rule `ES.74 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es74-prefer-to-declare-a-loop-variable-in-the-initializer-part-of-a-for-statement>`_ of the C++ Core Guidelines.
+
+It does also cover parts of:
+    - `ES.26 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es26-dont-use-a-variable-for-two-unrelated-purposes>`_
+    - `ES.5 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es5-keep-scopes-small>`_
+    - `ES.6 <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es6-declare-names-in-for-statement-initializers-and-conditions-to-limit-scope>`_
+
+
+.. code-block:: c++
+
+    void forLoopFunction() {
+        const int Limit{10};
+        int I{0};
+
+        // Should print a warning
+        for (; I < Limit; I++) {
+        }
+
+        // Should print a warning
+        for (I = 0; I < Limit; I++) {
+        }
+
+        // Good
+        for (int I{0}; I < Limit; I++) {
+        }
+    }
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -89,6 +89,11 @@
   Finds inner loops that have not been unrolled, as well as fully unrolled
   loops with unknown loops bounds or a large number of iterations.
 
+- New :doc:`cppcoreguidelines-declare-loop-variable-in-the-initializer
+  <clang-tidy/checks/cppcoreguidelines-declare-loop-variable-in-the-initializer>` check.
+
+  Checks if a loop variable is declared in the initializer part of a for-statement.
+
 - New :doc:`cppcoreguidelines-prefer-member-initializer
   <clang-tidy/checks/cppcoreguidelines-prefer-member-initializer>` check.
 
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareLoopVariableInTheInitializerCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareLoopVariableInTheInitializerCheck.h
@@ -0,0 +1,36 @@
+//===--- DeclareLoopVariableInTheInitializerCheck.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_CPPCOREGUIDELINES_DECLARELOOPVARIABLEINTHEINITIALIZERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_DECLARELOOPVARIABLEINTHEINITIALIZERCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+/// Checks if a loop variable is declared in the initializer part of a
+/// for-statement.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-declare-loop-variable-in-the-initializer.html
+class DeclareLoopVariableInTheInitializerCheck : public ClangTidyCheck {
+public:
+  DeclareLoopVariableInTheInitializerCheck(StringRef Name,
+                                           ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_DECLARELOOPVARIABLEINTHEINITIALIZERCHECK_H
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareLoopVariableInTheInitializerCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareLoopVariableInTheInitializerCheck.cpp
@@ -0,0 +1,35 @@
+//===--- DeclareLoopVariableInTheInitializerCheck.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 "DeclareLoopVariableInTheInitializerCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cppcoreguidelines {
+
+void DeclareLoopVariableInTheInitializerCheck::registerMatchers(
+    MatchFinder *Finder) {
+  Finder->addMatcher(forStmt(unless(has(declStmt()))).bind("forStmt"), this);
+}
+
+void DeclareLoopVariableInTheInitializerCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MatchedForStmt = Result.Nodes.getNodeAs<ForStmt>("forStmt");
+
+  diag(MatchedForStmt->getBeginLoc(),
+       "Prefer to declare a loop variable in the initializer part of a "
+       "for-statement");
+}
+
+} // namespace cppcoreguidelines
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -16,6 +16,7 @@
 #include "../readability/MagicNumbersCheck.h"
 #include "AvoidGotoCheck.h"
 #include "AvoidNonConstGlobalVariablesCheck.h"
+#include "DeclareLoopVariableInTheInitializerCheck.h"
 #include "InitVariablesCheck.h"
 #include "InterfacesGlobalInitCheck.h"
 #include "MacroUsageCheck.h"
@@ -52,6 +53,8 @@
         "cppcoreguidelines-avoid-magic-numbers");
     CheckFactories.registerCheck<AvoidNonConstGlobalVariablesCheck>(
         "cppcoreguidelines-avoid-non-const-global-variables");
+    CheckFactories.registerCheck<DeclareLoopVariableInTheInitializerCheck>(
+        "cppcoreguidelines-declare-loop-variable-in-the-initializer");
     CheckFactories.registerCheck<modernize::UseOverrideCheck>(
         "cppcoreguidelines-explicit-virtual-functions");
     CheckFactories.registerCheck<InitVariablesCheck>(
Index: clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -7,6 +7,7 @@
   AvoidGotoCheck.cpp
   AvoidNonConstGlobalVariablesCheck.cpp
   CppCoreGuidelinesTidyModule.cpp
+  DeclareLoopVariableInTheInitializerCheck.cpp
   InitVariablesCheck.cpp
   InterfacesGlobalInitCheck.cpp
   MacroUsageCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to