carlosgalvezp updated this revision to Diff 460419. carlosgalvezp added a comment.
Adjust warning message for consistency. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D132461/new/ https://reviews.llvm.org/D132461 Files: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidDoWhileCheck.cpp clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidDoWhileCheck.h clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp clang-tools-extra/docs/ReleaseNotes.rst clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-do-while.rst clang-tools-extra/docs/clang-tidy/checks/list.rst clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-do-while.cpp
Index: clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-do-while.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/avoid-do-while.cpp @@ -0,0 +1,88 @@ +// RUN: %check_clang_tidy -check-suffixes=DEFAULT %s cppcoreguidelines-avoid-do-while %t +// RUN: %check_clang_tidy -check-suffixes=IGNORE-MACROS %s cppcoreguidelines-avoid-do-while %t -- -config='{CheckOptions: [{key: cppcoreguidelines-avoid-do-while.IgnoreMacros, value: true}]}' + +#define FOO(x) \ + do { \ + } while (x != 0) + +#define BAR_0(x) \ + do { \ + bar(x); \ + } while (0) + +#define BAR_FALSE(x) \ + do { \ + bar(x); \ + } while (false) + +void bar(int); +int baz(); + +void foo() +{ + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+2]]:5: warning: avoid do-while loops [cppcoreguidelines-avoid-do-while] + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops [cppcoreguidelines-avoid-do-while] + do { + + } while(0); + + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+2]]:5: warning: avoid do-while loops + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops + do { + + } while(1); + + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+2]]:5: warning: avoid do-while loops + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops + do { + + } while(-1); + + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+2]]:5: warning: avoid do-while loops + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops + do { + + } while(false); + + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+2]]:5: warning: avoid do-while loops + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops + do { + + } while(true); + + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+3]]:5: warning: avoid do-while loops + // CHECK-MESSAGES-DEFAULT: :[[@LINE+2]]:5: warning: avoid do-while loops + int x1{0}; + do { + x1 = baz(); + } while (x1 > 0); + + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+2]]:5: warning: avoid do-while loops + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops + do { + + } while (x1 != 0); + + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+3]]:5: warning: avoid do-while loops + // CHECK-MESSAGES-DEFAULT: :[[@LINE+2]]:5: warning: avoid do-while loops + constexpr int x2{0}; + do { + + } while (x2); + + // CHECK-MESSAGES-IGNORE-MACROS: :[[@LINE+3]]:5: warning: avoid do-while loops + // CHECK-MESSAGES-DEFAULT: :[[@LINE+2]]:5: warning: avoid do-while loops + constexpr bool x3{false}; + do { + + } while (x3); + + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops + FOO(x1); + + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops + BAR_0(x1); + + // CHECK-MESSAGES-DEFAULT: :[[@LINE+1]]:5: warning: avoid do-while loops + BAR_FALSE(x1); +} 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 @@ -177,6 +177,7 @@ `concurrency-mt-unsafe <concurrency/mt-unsafe.html>`_, `concurrency-thread-canceltype-asynchronous <concurrency/thread-canceltype-asynchronous.html>`_, `cppcoreguidelines-avoid-const-or-ref-data-members <cppcoreguidelines/avoid-const-or-ref-data-members.html>`_, + `cppcoreguidelines-avoid-do-while <cppcoreguidelines/avoid-do-while.html>`_, `cppcoreguidelines-avoid-goto <cppcoreguidelines/avoid-goto.html>`_, `cppcoreguidelines-avoid-non-const-global-variables <cppcoreguidelines/avoid-non-const-global-variables.html>`_, `cppcoreguidelines-init-variables <cppcoreguidelines/init-variables.html>`_, "Yes" Index: clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-do-while.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines/avoid-do-while.rst @@ -0,0 +1,38 @@ +.. title:: clang-tidy - cppcoreguidelines-avoid-do-while + +cppcoreguidelines-avoid-do-while +================================ + +Warns when using ``do-while`` loops. They are less readable than plain ``while`` +loops, since the termination condition is at the end and the condition is not +checked prior to the first iteration. This can lead to subtle bugs. + +The check implements +`rule ES.75 of C++ Core Guidelines <https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Res-do>`_. + +Examples: + +.. code-block:: c++ + + int x; + do { + std::cin >> x; + // ... + } while (x < 0); + +Options +------- + +.. option:: IgnoreMacros + + Ignore the check when analyzing macros. This is useful for safely defining function-like macros: + + .. code-block:: c++ + + #define FOO_BAR(x) \ + do { \ + foo(x); \ + bar(x); \ + } while(0) + + Defaults to `false`. Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -104,6 +104,11 @@ Warns when a struct or class uses const or reference (lvalue or rvalue) data members. +- New :doc:`cppcoreguidelines-avoid-do-while + <clang-tidy/checks/cppcoreguidelines/avoid-do-while>` check. + + Warns when using ``do-while`` loops. + New check aliases ^^^^^^^^^^^^^^^^^ 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 @@ -15,6 +15,7 @@ #include "../modernize/UseOverrideCheck.h" #include "../readability/MagicNumbersCheck.h" #include "AvoidConstOrRefDataMembersCheck.h" +#include "AvoidDoWhileCheck.h" #include "AvoidGotoCheck.h" #include "AvoidNonConstGlobalVariablesCheck.h" #include "InitVariablesCheck.h" @@ -50,6 +51,8 @@ "cppcoreguidelines-avoid-c-arrays"); CheckFactories.registerCheck<AvoidConstOrRefDataMembersCheck>( "cppcoreguidelines-avoid-const-or-ref-data-members"); + CheckFactories.registerCheck<AvoidDoWhileCheck>( + "cppcoreguidelines-avoid-do-while"); CheckFactories.registerCheck<AvoidGotoCheck>( "cppcoreguidelines-avoid-goto"); CheckFactories.registerCheck<readability::MagicNumbersCheck>( 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 @@ -5,6 +5,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule AvoidConstOrRefDataMembersCheck.cpp + AvoidDoWhileCheck.cpp AvoidGotoCheck.cpp AvoidNonConstGlobalVariablesCheck.cpp CppCoreGuidelinesTidyModule.cpp Index: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidDoWhileCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidDoWhileCheck.h @@ -0,0 +1,41 @@ +//===--- AvoidDoWhileCheck.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_AVOIDDOWHILECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDDOWHILECHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +/// do-while loops are less readable than plan while loops, and can lead to +/// subtle bugs. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-do-while.html +class AvoidDoWhileCheck : public ClangTidyCheck { +public: + AvoidDoWhileCheck(StringRef Name, ClangTidyContext *Context); + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + bool IgnoreMacros; +}; + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_AVOIDDOWHILECHECK_H Index: clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidDoWhileCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/cppcoreguidelines/AvoidDoWhileCheck.cpp @@ -0,0 +1,41 @@ +//===--- AvoidDoWhileCheck.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 "AvoidDoWhileCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +AvoidDoWhileCheck::AvoidDoWhileCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", false)) {} + +void AvoidDoWhileCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "IgnoreMacros", IgnoreMacros); +} + +void AvoidDoWhileCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(doStmt().bind("x"), this); +} + +void AvoidDoWhileCheck::check(const MatchFinder::MatchResult &Result) { + if (const auto *MatchedDecl = Result.Nodes.getNodeAs<DoStmt>("x")) { + if (IgnoreMacros && MatchedDecl->getBeginLoc().isMacroID()) + return; + diag(MatchedDecl->getBeginLoc(), "avoid do-while loops"); + } +} + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits