diff options
author | Congcong Cai <congcongcai0907@163.com> | 2024-09-18 08:03:06 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-18 08:03:06 +0800 |
commit | 785624b28237bb75d4fa3b8e4219a5448b90eaac (patch) | |
tree | 5b408561e50492ab4aaf0e519feed86958f1b58c /clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp | |
parent | ca0613e0fcef2a9972f2802318201f8272e74693 (diff) | |
download | llvm-785624b28237bb75d4fa3b8e4219a5448b90eaac.zip llvm-785624b28237bb75d4fa3b8e4219a5448b90eaac.tar.gz llvm-785624b28237bb75d4fa3b8e4219a5448b90eaac.tar.bz2 |
[clang-tidy]suggest use `std::span` as replacement of c array in C++20 for modernize-avoid-c-arrays (#108555)
The incompleted C-Array in parameter does not own memory. Instead, It is
equivalent to pointer.
So we should not use `std::array` as recommended modern C++ replacement,
but use `std::vector` and `std::span` in C++20
Diffstat (limited to 'clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp')
-rw-r--r-- | clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp index 89790ea..9877819 100644 --- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp @@ -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; @@ -60,6 +61,7 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( typeLoc(hasValidBeginLoc(), hasType(arrayType()), + optionally(hasParent(parmVarDecl().bind("param_decl"))), unless(anyOf(hasParent(parmVarDecl(isArgvOfMain())), hasParent(varDecl(isExternC())), hasParent(fieldDecl( @@ -72,11 +74,28 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) { void AvoidCArraysCheck::check(const MatchFinder::MatchResult &Result) { const auto *ArrayType = Result.Nodes.getNodeAs<TypeLoc>("typeloc"); - + const bool IsInParam = + Result.Nodes.getNodeAs<ParmVarDecl>("param_decl") != nullptr; + const bool IsVLA = ArrayType->getTypePtr()->isVariableArrayType(); + enum class RecommendType { Array, Vector, Span }; + llvm::SmallVector<const char *> RecommendTypes{}; + if (IsVLA) { + RecommendTypes.push_back("std::vector<>"); + } else if (ArrayType->getTypePtr()->isIncompleteArrayType() && IsInParam) { + // in function parameter, we also don't know the size of + // IncompleteArrayType. + if (Result.Context->getLangOpts().CPlusPlus20) + RecommendTypes.push_back("std::span<>"); + else { + RecommendTypes.push_back("std::array<>"); + RecommendTypes.push_back("std::vector<>"); + } + } else { + RecommendTypes.push_back("std::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(); + "do not declare %select{C-style|C VLA}0 arrays, use %1 instead") + << IsVLA << llvm::join(RecommendTypes, " or "); } } // namespace clang::tidy::modernize |