Index: clang-tidy/modernize/AvoidCArraysCheck.h =================================================================== --- /dev/null +++ clang-tidy/modernize/AvoidCArraysCheck.h @@ -0,0 +1,35 @@ +//===--- AvoidCArraysCheck.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_MODERNIZE_AVOIDCARRAYSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_AVOIDCARRAYSCHECK_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace modernize { + +/// Find C-style array declarations and recommend to use std::array<>. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-avoid-c-arrays.html +class AvoidCArraysCheck : public ClangTidyCheck { +public: + AvoidCArraysCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace modernize +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_AVOIDCARRAYSCHECK_H Index: clang-tidy/modernize/AvoidCArraysCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/modernize/AvoidCArraysCheck.cpp @@ -0,0 +1,57 @@ +//===--- AvoidCArraysCheck.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 "AvoidCArraysCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace { + +AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) { + return Node.getBeginLoc().isValid(); +} + +AST_MATCHER_P(clang::TypeLoc, hasType, + clang::ast_matchers::internal::Matcher, + InnerMatcher) { + const clang::Type *TypeNode = Node.getTypePtr(); + return (TypeNode != nullptr && + InnerMatcher.matches(*TypeNode, Finder, Builder)); +} + +} // namespace + +namespace clang { +namespace tidy { +namespace modernize { + +void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) { + // std::array<> is avaliable since C++11. + if (!getLangOpts().CPlusPlus11) + return; + + Finder->addMatcher( + typeLoc(hasValidBeginLoc(), hasType(arrayType()), + unless(anyOf(hasParent(varDecl(isExternC())), + hasAncestor(functionDecl(isExternC()))))) + .bind("typeloc"), + this); +} + +void AvoidCArraysCheck::check(const MatchFinder::MatchResult &Result) { + const auto *ArrayType = Result.Nodes.getNodeAs("typeloc"); + diag(ArrayType->getBeginLoc(), + "do not declare C-style arrays, use std::array<> instead"); +} + +} // namespace modernize +} // namespace tidy +} // namespace clang Index: clang-tidy/modernize/CMakeLists.txt =================================================================== --- clang-tidy/modernize/CMakeLists.txt +++ clang-tidy/modernize/CMakeLists.txt @@ -2,6 +2,7 @@ add_clang_library(clangTidyModernizeModule AvoidBindCheck.cpp + AvoidCArraysCheck.cpp ConcatNestedNamespacesCheck.cpp DeprecatedHeadersCheck.cpp DeprecatedIosBaseAliasesCheck.cpp Index: clang-tidy/modernize/ModernizeTidyModule.cpp =================================================================== --- clang-tidy/modernize/ModernizeTidyModule.cpp +++ clang-tidy/modernize/ModernizeTidyModule.cpp @@ -11,6 +11,7 @@ #include "../ClangTidyModule.h" #include "../ClangTidyModuleRegistry.h" #include "AvoidBindCheck.h" +#include "AvoidCArraysCheck.h" #include "ConcatNestedNamespacesCheck.h" #include "DeprecatedHeadersCheck.h" #include "DeprecatedIosBaseAliasesCheck.h" @@ -48,6 +49,7 @@ public: void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { CheckFactories.registerCheck("modernize-avoid-bind"); + CheckFactories.registerCheck("modernize-avoid-c-arrays"); CheckFactories.registerCheck( "modernize-concat-nested-namespaces"); CheckFactories.registerCheck( Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -123,6 +123,11 @@ but also have logic (non-static member functions), and diagnoses all member variables that have any other scope other than ``private``. +- New :doc:`modernize-avoid-c-arrays + ` check. + + Finds C-style array declarations and recommend to use ``std::array<>``. + - New :doc:`modernize-concat-nested-namespaces ` check. Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -178,6 +178,7 @@ misc-unused-parameters misc-unused-using-decls modernize-avoid-bind + modernize-avoid-c-arrays modernize-concat-nested-namespaces modernize-deprecated-headers modernize-deprecated-ios-base-aliases Index: docs/clang-tidy/checks/modernize-avoid-c-arrays.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/modernize-avoid-c-arrays.rst @@ -0,0 +1,53 @@ +.. title:: clang-tidy - modernize-avoid-c-arrays + +modernize-avoid-c-arrays +=================== + +Finds C-style array declarations and recommend to use ``std::array<>``. +All types of C arrays are diagnosed. + +However, no fix-its are provided. Such transform would need to be able to +observe *all* the uses of said declaration in order to decide whether it is +safe to transform or not, and that is impossible in case of headers. + +.. code:: c++ + + int a[] = {1, 2}; // warning: do not declare C-style arrays, use std::array<> instead + + int b[1]; // warning: do not declare C-style arrays, use std::array<> instead + + void foo() { + int c[b[0]]; // warning: do not declare C-style arrays, use std::array<> instead + } + + template + class array { + T d[Size]; // warning: do not declare C-style arrays, use std::array<> instead + + int e[1]; // warning: do not declare C-style arrays, use std::array<> instead + }; + + array d; // warning: do not declare C-style arrays, use std::array<> instead + + using k = int[4]; // warning: do not declare C-style arrays, use std::array<> instead + + +However, the ``extern "C"`` code is ignored, since it is common to share +such headers between C code, and C++ code. + +.. code:: c++ + + // Some header + extern "C" { + + int f[] = {1, 2}; // not diagnosed + + int j[1]; // not diagnosed + + inline void bar() { + { + int j[j[0]]; // not diagnosed + } + } + + } Index: test/clang-tidy/modernize-avoid-c-arrays.cpp =================================================================== --- /dev/null +++ test/clang-tidy/modernize-avoid-c-arrays.cpp @@ -0,0 +1,59 @@ +// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t + +int a[] = {1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead + +int b[1]; +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead + +void foo() { + int c[b[0]]; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead +} + +template +class array { + T d[Size]; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead + + int e[1]; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead +}; + +array d; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not declare C-style arrays, use std::array<> instead + +using k = int[4]; +// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: do not declare C-style arrays, use std::array<> instead + +array dk; + +template +class unique_ptr { + T *d; + + int e[1]; + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead +}; + +unique_ptr d2; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead + +using k2 = int[]; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, use std::array<> instead + +unique_ptr dk2; + +// Some header +extern "C" { + +int f[] = {1, 2}; + +int j[1]; + +inline void bar() { + { + int j[j[0]]; + } +} +}