Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: [[ https://bugs.llvm.org/show_bug.cgi?id=39224 | PR39224 ]] As discussed, we can't always do the transform automatically due to that array-to-pointer decay of C array. In order to detect whether we can do said transform, we'd need to be able to see all usages of said array, which is, i would say, rather impossible if e.g. it is in the header. Thus right now no fixit exists. Exceptions: `extern "C"` code. References: * [[ https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#es27-use-stdarray-or-stack_array-for-arrays-on-the-stack | CPPCG ES.27: Use std::array or stack_array for arrays on the stack ]] * [[ https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#slcon1-prefer-using-stl-array-or-vector-instead-of-a-c-array | CPPCG SL.con.1: Prefer using STL array or vector instead of a C array ]] * HICPP `4.1.1 Ensure that a function argument does not undergo an array-to-pointer conversion` * MISRA `5-2-12 An identifier with array type passed as a function argument shall not decay to a pointer` Reviewers: aaron.ballman, JonasToth, alexfh, hokein, xazax.hun Reviewed By: JonasToth Subscribers: Eugene.Zelenko, mgorny, rnkovacs, cfe-commits Tags: #clang-tools-extra Differential Revision: https://reviews.llvm.org/D53771 llvm-svn: 346835
- Loading branch information
Showing
13 changed files
with
297 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
69 changes: 69 additions & 0 deletions
69
clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
//===--- 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<clang::Type>, | ||
InnerMatcher) { | ||
const clang::Type *TypeNode = Node.getTypePtr(); | ||
return TypeNode != nullptr && | ||
InnerMatcher.matches(*TypeNode, Finder, Builder); | ||
} | ||
|
||
AST_MATCHER(clang::RecordDecl, isExternCContext) { | ||
return Node.isExternCContext(); | ||
} | ||
|
||
} // 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())), | ||
hasParent(fieldDecl( | ||
hasParent(recordDecl(isExternCContext())))), | ||
hasAncestor(functionDecl(isExternC()))))) | ||
.bind("typeloc"), | ||
this); | ||
} | ||
|
||
void AvoidCArraysCheck::check(const MatchFinder::MatchResult &Result) { | ||
const auto *ArrayType = Result.Nodes.getNodeAs<TypeLoc>("typeloc"); | ||
|
||
static constexpr llvm::StringLiteral UseArray = llvm::StringLiteral( | ||
"do not declare C-style arrays, use std::array<> instead"); | ||
static constexpr llvm::StringLiteral UseVector = llvm::StringLiteral( | ||
"do not declare C VLA arrays, use std::vector<> instead"); | ||
|
||
diag(ArrayType->getBeginLoc(), | ||
ArrayType->getTypePtr()->isVariableArrayType() ? UseVector : UseArray); | ||
} | ||
|
||
} // namespace modernize | ||
} // namespace tidy | ||
} // namespace clang |
35 changes: 35 additions & 0 deletions
35
clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 types and recommend to use std::array<> / std::vector<>. | ||
/// | ||
/// 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
clang-tools-extra/docs/clang-tidy/checks/cppcoreguidelines-avoid-c-arrays.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
.. title:: clang-tidy - cppcoreguidelines-avoid-c-arrays | ||
.. meta:: | ||
:http-equiv=refresh: 5;URL=modernize-avoid-c-arrays.html | ||
|
||
cppcoreguidelines-avoid-c-arrays | ||
================================ | ||
|
||
The cppcoreguidelines-avoid-c-arrays check is an alias, please see | ||
`modernize-avoid-c-arrays <modernize-avoid-c-arrays.html>`_ | ||
for more information. |
10 changes: 10 additions & 0 deletions
10
clang-tools-extra/docs/clang-tidy/checks/hicpp-avoid-c-arrays.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
.. title:: clang-tidy - hicpp-avoid-c-arrays | ||
.. meta:: | ||
:http-equiv=refresh: 5;URL=modernize-avoid-c-arrays.html | ||
|
||
hicpp-avoid-c-arrays | ||
==================== | ||
|
||
The hicpp-avoid-c-arrays check is an alias, please see | ||
`modernize-avoid-c-arrays <modernize-avoid-c-arrays.html>`_ | ||
for more information. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
clang-tools-extra/docs/clang-tidy/checks/modernize-avoid-c-arrays.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
.. title:: clang-tidy - modernize-avoid-c-arrays | ||
|
||
modernize-avoid-c-arrays | ||
======================== | ||
|
||
`cppcoreguidelines-avoid-c-arrays` redirects here as an alias for this check. | ||
|
||
`hicpp-avoid-c-arrays` redirects here as an alias for this check. | ||
|
||
Finds C-style array types and recommend to use ``std::array<>`` / | ||
``std::vector<>``. All types of C arrays are diagnosed. | ||
|
||
However, fix-it are potentially dangerous in header files and are therefore not | ||
emitted right now. | ||
|
||
.. 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 VLA arrays, use std::vector<> instead | ||
} | ||
|
||
template <typename T, int Size> | ||
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<int[4], 2> 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 | ||
} | ||
} | ||
|
||
} |
88 changes: 88 additions & 0 deletions
88
clang-tools-extra/test/clang-tidy/modernize-avoid-c-arrays.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// 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 VLA arrays, use std::vector<> instead | ||
|
||
using d = decltype(c); | ||
d e; | ||
// Semi-FIXME: we do not diagnose these last two lines separately, | ||
// because we point at typeLoc.getBeginLoc(), which is the decl before that | ||
// (int c[b[0]];), which is already diagnosed. | ||
} | ||
|
||
template <typename T, int Size> | ||
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<int[4], 2> 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<k, 2> dk; | ||
|
||
template <typename T> | ||
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<int[]> 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<k2> dk2; | ||
|
||
// Some header | ||
extern "C" { | ||
|
||
int f[] = {1, 2}; | ||
|
||
int j[1]; | ||
|
||
inline void bar() { | ||
{ | ||
int j[j[0]]; | ||
} | ||
} | ||
|
||
extern "C++" { | ||
int f3[] = {1, 2}; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead | ||
|
||
int j3[1]; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use std::array<> instead | ||
|
||
struct Foo { | ||
int f3[3] = {1, 2}; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead | ||
|
||
int j3[1]; | ||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead | ||
}; | ||
} | ||
|
||
struct Bar { | ||
|
||
int f[3] = {1, 2}; | ||
|
||
int j[1]; | ||
}; | ||
} |