[clang-tools-extra] [clang-tidy] Add AllowStringArrays option to modernize-avoid-c-arrays (PR #71701)
Piotr Zegar via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 31 11:26:38 PST 2024
https://github.com/PiotrZSL updated https://github.com/llvm/llvm-project/pull/71701
>From 050d53bdbc01be93a15f6851faddc24e520f0472 Mon Sep 17 00:00:00 2001
From: Piotr Zegar <me at piotrzegar.pl>
Date: Wed, 8 Nov 2023 16:52:06 +0000
Subject: [PATCH 1/4] [clang-tidy] Add AllowStringArrays option to
modernize-avoid-c-arrays
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.
---
.../modernize/AvoidCArraysCheck.cpp | 21 +++++++++++++++++--
.../clang-tidy/modernize/AvoidCArraysCheck.h | 14 +++++++++----
clang-tools-extra/docs/ReleaseNotes.rst | 5 +++++
.../checks/modernize/avoid-c-arrays.rst | 9 ++++++++
.../avoid-c-arrays-ignores-strings.cpp | 6 ++++++
.../checkers/modernize/avoid-c-arrays.cpp | 3 +++
6 files changed, 52 insertions(+), 6 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-ignores-strings.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
index d1b15479ffe7a..ab1cdd62aa2cc 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
@@ -12,6 +12,8 @@
using namespace clang::ast_matchers;
+namespace clang::tidy::modernize {
+
namespace {
AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
@@ -38,16 +40,31 @@ AST_MATCHER(clang::ParmVarDecl, isArgvOfMain) {
} // namespace
-namespace clang::tidy::modernize {
+AvoidCArraysCheck::AvoidCArraysCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ AllowStringArrays(Options.get("AllowStringArrays", false)) {}
+
+void AvoidCArraysCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "AllowStringArrays", AllowStringArrays);
+}
void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) {
+ ast_matchers::internal::Matcher<TypeLoc> IgnoreStringArrayIfNeededMatcher =
+ anything();
+ if (AllowStringArrays)
+ IgnoreStringArrayIfNeededMatcher =
+ unless(typeLoc(loc(hasCanonicalType(incompleteArrayType(
+ hasElementType(isAnyCharacter())))),
+ hasParent(varDecl(hasInitializer(stringLiteral())))));
+
Finder->addMatcher(
typeLoc(hasValidBeginLoc(), hasType(arrayType()),
unless(anyOf(hasParent(parmVarDecl(isArgvOfMain())),
hasParent(varDecl(isExternC())),
hasParent(fieldDecl(
hasParent(recordDecl(isExternCContext())))),
- hasAncestor(functionDecl(isExternC())))))
+ hasAncestor(functionDecl(isExternC())))),
+ std::move(IgnoreStringArrayIfNeededMatcher))
.bind("typeloc"),
this);
}
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
index 7099f99c86949..719e88e4b3166 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
@@ -19,13 +19,19 @@ namespace clang::tidy::modernize {
/// 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) {}
+ AvoidCArraysCheck(StringRef Name, ClangTidyContext *Context);
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
return LangOpts.CPlusPlus11;
}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+ std::optional<TraversalKind> getCheckTraversalKind() const override {
+ return TK_IgnoreUnlessSpelledInSource;
+ }
+
+private:
+ const bool AllowStringArrays;
};
} // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index fd2cba4e4f463..94b51f919f80a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -106,6 +106,11 @@ New check aliases
Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^
+- Improved :doc:`modernize-avoid-c-arrays
+ <clang-tidy/checks/modernize/avoid-c-arrays>` check by introducing the new
+ `AllowStringArrays` option, enabling the exclusion of array types with deduced
+ sizes constructed from string literals.
+
Removed checks
^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
index bc61033ff1fa1..acc628d58f80e 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
@@ -58,3 +58,12 @@ such headers between C code, and C++ code.
Similarly, the ``main()`` function is ignored. Its second and third parameters
can be either ``char* argv[]`` or ``char** argv``, but cannot be
``std::array<>``.
+
+.. option:: AllowStringArrays
+
+ When set to `true` (default is `false`), incomplete array types constructed
+ from string literals will be ignored. Example:
+
+ .. code:: c++
+
+ const char name[] = "Some name";
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-ignores-strings.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-ignores-strings.cpp
new file mode 100644
index 0000000000000..545429b2be807
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-ignores-strings.cpp
@@ -0,0 +1,6 @@
+// RUN: %check_clang_tidy %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]
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
index dd3078010eb38..4233f69337898 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -86,3 +86,6 @@ struct Bar {
int j[1];
};
}
+
+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]
>From b4c4573d505fe0df63ed4252fb49e46e5c1a7afb Mon Sep 17 00:00:00 2001
From: Piotr Zegar <me at piotrzegar.pl>
Date: Mon, 29 Jan 2024 22:44:31 +0000
Subject: [PATCH 2/4] Explicitly exclude function arguments
---
clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp | 5 ++---
.../checkers/modernize/avoid-c-arrays-ignores-strings.cpp | 3 +++
.../test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp | 3 +++
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
index ab1cdd62aa2cc..8118d8335853a 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
@@ -53,9 +53,8 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) {
anything();
if (AllowStringArrays)
IgnoreStringArrayIfNeededMatcher =
- unless(typeLoc(loc(hasCanonicalType(incompleteArrayType(
- hasElementType(isAnyCharacter())))),
- hasParent(varDecl(hasInitializer(stringLiteral())))));
+ unless(typeLoc(loc(hasCanonicalType(incompleteArrayType(hasElementType(isAnyCharacter())))),
+ hasParent(varDecl(hasInitializer(stringLiteral()), unless(parmVarDecl())))));
Finder->addMatcher(
typeLoc(hasValidBeginLoc(), hasType(arrayType()),
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-ignores-strings.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-ignores-strings.cpp
index 545429b2be807..f6d64848f9e3a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-ignores-strings.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-ignores-strings.cpp
@@ -4,3 +4,6 @@
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]
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
index 4233f69337898..ce99f0821b223 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays.cpp
@@ -89,3 +89,6 @@ struct Bar {
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]
>From 3d108c3e30aa7b63dbfbaff76f7309e5b9e0d4f3 Mon Sep 17 00:00:00 2001
From: Piotr Zegar <me at piotrzegar.pl>
Date: Wed, 31 Jan 2024 17:57:55 +0000
Subject: [PATCH 3/4] Formating
---
.../clang-tidy/modernize/AvoidCArraysCheck.cpp | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
index 8118d8335853a..89790ea70cf22 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
@@ -53,8 +53,10 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) {
anything();
if (AllowStringArrays)
IgnoreStringArrayIfNeededMatcher =
- unless(typeLoc(loc(hasCanonicalType(incompleteArrayType(hasElementType(isAnyCharacter())))),
- hasParent(varDecl(hasInitializer(stringLiteral()), unless(parmVarDecl())))));
+ unless(typeLoc(loc(hasCanonicalType(incompleteArrayType(
+ hasElementType(isAnyCharacter())))),
+ hasParent(varDecl(hasInitializer(stringLiteral()),
+ unless(parmVarDecl())))));
Finder->addMatcher(
typeLoc(hasValidBeginLoc(), hasType(arrayType()),
>From cebb72648c62650d607bfcc11a349860f4898e1d Mon Sep 17 00:00:00 2001
From: Piotr Zegar <me at piotrzegar.pl>
Date: Wed, 31 Jan 2024 19:26:25 +0000
Subject: [PATCH 4/4] Update documentation
---
clang-tools-extra/docs/ReleaseNotes.rst | 2 +-
.../docs/clang-tidy/checks/modernize/avoid-c-arrays.rst | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 94b51f919f80a..9f183f615da49 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -109,7 +109,7 @@ Changes in existing checks
- Improved :doc:`modernize-avoid-c-arrays
<clang-tidy/checks/modernize/avoid-c-arrays>` check by introducing the new
`AllowStringArrays` option, enabling the exclusion of array types with deduced
- sizes constructed from string literals.
+ length initialized from string literals.
Removed checks
^^^^^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
index acc628d58f80e..8f13ca4466a31 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/avoid-c-arrays.rst
@@ -61,8 +61,10 @@ can be either ``char* argv[]`` or ``char** argv``, but cannot be
.. option:: AllowStringArrays
- When set to `true` (default is `false`), incomplete array types constructed
- from string literals will be ignored. Example:
+ When set to `true` (default is `false`), variables of character array type
+ with deduced length, initialized directly from string literals, will be ignored.
+ This option doesn't affect cases where length can't be deduced, resembling
+ pointers, as seen in class members and parameters. Example:
.. code:: c++
More information about the cfe-commits
mailing list