Skip to content

[clang-tidy]suggest use std::span as replacement of c array in C++20 for modernize-avoid-c-arrays #108555

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "AvoidCArraysCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"

using namespace clang::ast_matchers;

Expand Down Expand Up @@ -38,6 +39,13 @@ AST_MATCHER(clang::ParmVarDecl, isArgvOfMain) {
return FD ? FD->isMain() : false;
}

AST_MATCHER_P(clang::TypeLoc, alwaysTrue,
clang::ast_matchers::internal::Matcher<clang::TypeLoc>,
InnerMatcher) {
InnerMatcher.matches(Node, Finder, Builder);
return true;
}

} // namespace

AvoidCArraysCheck::AvoidCArraysCheck(StringRef Name, ClangTidyContext *Context)
Expand All @@ -60,6 +68,7 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) {

Finder->addMatcher(
typeLoc(hasValidBeginLoc(), hasType(arrayType()),
alwaysTrue(hasParent(parmVarDecl().bind("param_decl"))),
unless(anyOf(hasParent(parmVarDecl(isArgvOfMain())),
hasParent(varDecl(isExternC())),
hasParent(fieldDecl(
Expand All @@ -72,11 +81,22 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) {

void AvoidCArraysCheck::check(const MatchFinder::MatchResult &Result) {
const auto *ArrayType = Result.Nodes.getNodeAs<TypeLoc>("typeloc");

bool const IsInParam =
Result.Nodes.getNodeAs<ParmVarDecl>("param_decl") != nullptr;
const bool IsVLA = ArrayType->getTypePtr()->isVariableArrayType();
// in function parameter, we also don't know the size of IncompleteArrayType.
const bool IsUnknownSize =
IsVLA || (ArrayType->getTypePtr()->isIncompleteArrayType() && IsInParam);
enum class RecommendType { Array, Vector, Span };
const RecommendType RecommendType =
(IsInParam && Result.Context->getLangOpts().CPlusPlus20)
? RecommendType::Span
: IsUnknownSize ? RecommendType::Vector
: RecommendType::Array;
diag(ArrayType->getBeginLoc(),
"do not declare %select{C-style|C VLA}0 arrays, use "
"%select{std::array<>|std::vector<>}0 instead")
<< ArrayType->getTypePtr()->isVariableArrayType();
"%select{std::array<>|std::vector<>|std::span<>}1 instead")
<< IsVLA << static_cast<int>(RecommendType);
}

} // namespace clang::tidy::modernize
4 changes: 4 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ Changes in existing checks
<clang-tidy/checks/bugprone/casting-through-void>` check to suggest replacing
the offending code with ``reinterpret_cast``, to more clearly express intent.

- Improved :doc:`modernize-avoid-c-arrays
<clang-tidy/checks/modernize/avoid-c-arrays>` check to suggest use std::span
as replacement of c array in C++20.

- Improved :doc:`modernize-use-std-format
<clang-tidy/checks/modernize/use-std-format>` check to support replacing
member function calls too.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// RUN: %check_clang_tidy -std=c++20 %s modernize-avoid-c-arrays %t

int foo(int data[], int size) {
// CHECK-MESSAGES: :[[@LINE-1]]:9: warning: do not declare C-style arrays, use std::span<> instead
int f4[] = {1, 2};
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
// RUN: %check_clang_tidy -std=c++17 %s modernize-avoid-c-arrays %t

int not_main(int argc, char *argv[]) {
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::array<> instead
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::vector<> instead
int f4[] = {1, 2};
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
}
Expand All @@ -11,7 +11,7 @@ int main(int argc, char *argv[]) {
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead

auto not_main = [](int argc, char *argv[]) {
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::array<> instead
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::vector<> instead
int f6[] = {1, 2};
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not declare C-style arrays, use std::array<> instead
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t -- \
// RUN: %check_clang_tidy -std=c++17 %s modernize-avoid-c-arrays %t -- \
// RUN: -config='{CheckOptions: { modernize-avoid-c-arrays.AllowStringArrays: true }}'

const char name[] = "name";
const char array[] = {'n', 'a', 'm', 'e', '\0'};
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]

void takeCharArray(const char name[]);
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not declare C-style arrays, use std::vector<> instead [modernize-avoid-c-arrays]
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
// RUN: %check_clang_tidy -std=c++17 %s modernize-avoid-c-arrays %t

int not_main(int argc, char *argv[], char *argw[]) {
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::array<> instead
// CHECK-MESSAGES: :[[@LINE-2]]:38: warning: do not declare C-style arrays, use std::array<> instead
// CHECK-MESSAGES: :[[@LINE-1]]:24: warning: do not declare C-style arrays, use std::vector<> instead
// CHECK-MESSAGES: :[[@LINE-2]]:38: warning: do not declare C-style arrays, use std::vector<> instead
int f4[] = {1, 2};
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead
}
Expand All @@ -12,8 +12,8 @@ int main(int argc, char *argv[], char *argw[]) {
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, use std::array<> instead

auto not_main = [](int argc, char *argv[], char *argw[]) {
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::array<> instead
// CHECK-MESSAGES: :[[@LINE-2]]:46: warning: do not declare C-style arrays, use std::array<> instead
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: do not declare C-style arrays, use std::vector<> instead
// CHECK-MESSAGES: :[[@LINE-2]]:46: warning: do not declare C-style arrays, use std::vector<> instead
int f6[] = {1, 2};
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: do not declare C-style arrays, use std::array<> instead
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t
// RUN: %check_clang_tidy -std=c++17 %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
Expand Down Expand Up @@ -91,4 +91,4 @@ const char name[] = "Some string";
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]

void takeCharArray(const char name[]);
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not declare C-style arrays, use std::vector<> instead [modernize-avoid-c-arrays]
Loading