Index: clang-tidy/cppcoreguidelines/CMakeLists.txt =================================================================== --- clang-tidy/cppcoreguidelines/CMakeLists.txt +++ clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -3,6 +3,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule CppCoreGuidelinesTidyModule.cpp InterfacesGlobalInitCheck.cpp + OneNamePerDeclarationCheck.cpp ProBoundsArrayToPointerDecayCheck.cpp ProBoundsConstantArrayIndexCheck.cpp ProBoundsPointerArithmeticCheck.cpp Index: clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp =================================================================== --- clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -12,6 +12,7 @@ #include "../ClangTidyModuleRegistry.h" #include "../misc/UnconventionalAssignOperatorCheck.h" #include "InterfacesGlobalInitCheck.h" +#include "OneNamePerDeclarationCheck.h" #include "ProBoundsArrayToPointerDecayCheck.h" #include "ProBoundsConstantArrayIndexCheck.h" #include "ProBoundsPointerArithmeticCheck.h" @@ -35,6 +36,8 @@ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { CheckFactories.registerCheck( "cppcoreguidelines-interfaces-global-init"); + CheckFactories.registerCheck( + "cppcoreguidelines-one-name-per-declaration"); CheckFactories.registerCheck( "cppcoreguidelines-pro-bounds-array-to-pointer-decay"); CheckFactories.registerCheck( Index: clang-tidy/cppcoreguidelines/OneNamePerDeclarationCheck.h =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/OneNamePerDeclarationCheck.h @@ -0,0 +1,35 @@ +//===--- OneNamePerDeclarationCheck.h - clang-tidy---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_ONE_NAME_PER_DECLARATION_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_ONE_NAME_PER_DECLARATION_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +/// This check warns about multiple names in one declaration. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-one-name-per-declaration.html +class OneNamePerDeclarationCheck : public ClangTidyCheck { +public: + OneNamePerDeclarationCheck(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_ONE_NAME_PER_DECLARATION_H Index: clang-tidy/cppcoreguidelines/OneNamePerDeclarationCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/cppcoreguidelines/OneNamePerDeclarationCheck.cpp @@ -0,0 +1,51 @@ +//===--- OneNamePerDeclarationCheck.cpp - clang-tidy-----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "OneNamePerDeclarationCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace cppcoreguidelines { + +namespace { + +AST_MATCHER_P(DeclStmt, declCountIsGreaterThan, unsigned, N) { + return std::distance(Node.decl_begin(), Node.decl_end()) > (ptrdiff_t)N; +} + +} // end anonymous namespace + +void OneNamePerDeclarationCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + declStmt(declCountIsGreaterThan(1)).bind("multipleNameDeclaration"), + this); +} + +void OneNamePerDeclarationCheck::check(const MatchFinder::MatchResult &Result) { + // FIXME: Also provide diagnostics splitting the declarations. E.g. + // + // Before: + // int x = 42, y = 43, z = 44; + // After: + // int x = 42; + // int y = 43; + // int z = 44; + const auto *MultipleNameDeclaration = + Result.Nodes.getNodeAs("multipleNameDeclaration"); + diag(MultipleNameDeclaration->getStartLoc(), + "Do not declare multiple names per declaration"); +} + +} // namespace cppcoreguidelines +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/cppcoreguidelines-one-name-per-declaration.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/cppcoreguidelines-one-name-per-declaration.rst @@ -0,0 +1,29 @@ +.. title:: clang-tidy - cppcoreguidelines-one-name-per-declaration + +cppcoreguidelines-one-name-per-declaration +========================================== + +Checks for declarations with multiple names. C++ Core Guidelines suggests to +split such declarations into multiple declarations each containing one name. + +This would improve readability and prevents potential bugs caused by inattention +and C/C++ syntax specifics. + +Example, bad. + +.. code-block:: c++ + + std::vector velocities(10, 0), numbers(other_numbers), + inputs(input.begin(), input.end()); + +Example, good. + +.. code-block:: c++ + + std::vector velocities(10, 0); + std::vector numbers(other_numbers); + std::vector inputs(input.begin(), input.end()); + +This rule is part of the "Expressions and statements" profile of the C++ Core +Guidelines, see +http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#a-nameres-name-oneaes10-declare-one-name-only-per-declaration Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -19,6 +19,7 @@ cert-flp30-c cert-oop11-cpp (redirects to misc-move-constructor-init) cppcoreguidelines-interfaces-global-init + cppcoreguidelines-one-name-per-declaration cppcoreguidelines-pro-bounds-array-to-pointer-decay cppcoreguidelines-pro-bounds-constant-array-index cppcoreguidelines-pro-bounds-pointer-arithmetic Index: test/clang-tidy/cppcoreguidelines-one-name-per-declaration.cpp =================================================================== --- /dev/null +++ test/clang-tidy/cppcoreguidelines-one-name-per-declaration.cpp @@ -0,0 +1,16 @@ +// RUN: %check_clang_tidy %s cppcoreguidelines-one-name-per-declaration %t + +int main() { + { + int x = 42; + } + { + int x = 42, y = 43; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: Do not declare multiple names per declaration [cppcoreguidelines-one-name-per-declaration] + } + { + int x = 42, y = 43, z = 44; + // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: Do not declare multiple names per declaration + } + return 0; +}