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