Skip to content

Commit b777bb7

Browse files
authored
[clang-tidy] Add AllowStringArrays option to modernize-avoid-c-arrays (#71701)
Add AllowStringArrays option, enabling the exclusion of array types with deduced sizes constructed from string literals. This includes only var declarations of array of characters constructed directly from c-strings. Closes #59475
1 parent 8eea582 commit b777bb7

File tree

6 files changed

+61
-6
lines changed

6 files changed

+61
-6
lines changed

clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
using namespace clang::ast_matchers;
1414

15+
namespace clang::tidy::modernize {
16+
1517
namespace {
1618

1719
AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
@@ -38,16 +40,32 @@ AST_MATCHER(clang::ParmVarDecl, isArgvOfMain) {
3840

3941
} // namespace
4042

41-
namespace clang::tidy::modernize {
43+
AvoidCArraysCheck::AvoidCArraysCheck(StringRef Name, ClangTidyContext *Context)
44+
: ClangTidyCheck(Name, Context),
45+
AllowStringArrays(Options.get("AllowStringArrays", false)) {}
46+
47+
void AvoidCArraysCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
48+
Options.store(Opts, "AllowStringArrays", AllowStringArrays);
49+
}
4250

4351
void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) {
52+
ast_matchers::internal::Matcher<TypeLoc> IgnoreStringArrayIfNeededMatcher =
53+
anything();
54+
if (AllowStringArrays)
55+
IgnoreStringArrayIfNeededMatcher =
56+
unless(typeLoc(loc(hasCanonicalType(incompleteArrayType(
57+
hasElementType(isAnyCharacter())))),
58+
hasParent(varDecl(hasInitializer(stringLiteral()),
59+
unless(parmVarDecl())))));
60+
4461
Finder->addMatcher(
4562
typeLoc(hasValidBeginLoc(), hasType(arrayType()),
4663
unless(anyOf(hasParent(parmVarDecl(isArgvOfMain())),
4764
hasParent(varDecl(isExternC())),
4865
hasParent(fieldDecl(
4966
hasParent(recordDecl(isExternCContext())))),
50-
hasAncestor(functionDecl(isExternC())))))
67+
hasAncestor(functionDecl(isExternC())))),
68+
std::move(IgnoreStringArrayIfNeededMatcher))
5169
.bind("typeloc"),
5270
this);
5371
}

clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,19 @@ namespace clang::tidy::modernize {
1919
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/avoid-c-arrays.html
2020
class AvoidCArraysCheck : public ClangTidyCheck {
2121
public:
22-
AvoidCArraysCheck(StringRef Name, ClangTidyContext *Context)
23-
: ClangTidyCheck(Name, Context) {}
22+
AvoidCArraysCheck(StringRef Name, ClangTidyContext *Context);
23+
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
24+
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
25+
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
2426
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
2527
return LangOpts.CPlusPlus11;
2628
}
27-
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
28-
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
29+
std::optional<TraversalKind> getCheckTraversalKind() const override {
30+
return TK_IgnoreUnlessSpelledInSource;
31+
}
32+
33+
private:
34+
const bool AllowStringArrays;
2935
};
3036

3137
} // namespace clang::tidy::modernize

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,11 @@ New check aliases
106106
Changes in existing checks
107107
^^^^^^^^^^^^^^^^^^^^^^^^^^
108108

109+
- Improved :doc:`modernize-avoid-c-arrays
110+
<clang-tidy/checks/modernize/avoid-c-arrays>` check by introducing the new
111+
`AllowStringArrays` option, enabling the exclusion of array types with deduced
112+
length initialized from string literals.
113+
109114
Removed checks
110115
^^^^^^^^^^^^^^
111116

clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,14 @@ such headers between C code, and C++ code.
5858
Similarly, the ``main()`` function is ignored. Its second and third parameters
5959
can be either ``char* argv[]`` or ``char** argv``, but cannot be
6060
``std::array<>``.
61+
62+
.. option:: AllowStringArrays
63+
64+
When set to `true` (default is `false`), variables of character array type
65+
with deduced length, initialized directly from string literals, will be ignored.
66+
This option doesn't affect cases where length can't be deduced, resembling
67+
pointers, as seen in class members and parameters. Example:
68+
69+
.. code:: c++
70+
71+
const char name[] = "Some name";
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// RUN: %check_clang_tidy %s modernize-avoid-c-arrays %t -- \
2+
// RUN: -config='{CheckOptions: { modernize-avoid-c-arrays.AllowStringArrays: true }}'
3+
4+
const char name[] = "name";
5+
const char array[] = {'n', 'a', 'm', 'e', '\0'};
6+
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]
7+
8+
void takeCharArray(const char name[]);
9+
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]

clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,9 @@ struct Bar {
8686
int j[1];
8787
};
8888
}
89+
90+
const char name[] = "Some string";
91+
// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]
92+
93+
void takeCharArray(const char name[]);
94+
// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: do not declare C-style arrays, use std::array<> instead [modernize-avoid-c-arrays]

0 commit comments

Comments
 (0)