https://github.com/stmuench updated 
https://github.com/llvm/llvm-project/pull/131468

>From b5457130eb02f32e83416747b770b281b477d5cd Mon Sep 17 00:00:00 2001
From: stmuench <stmue...@gmx.net>
Date: Sat, 15 Mar 2025 21:00:52 +0100
Subject: [PATCH] [clang-tidy] offer option to check sugared types in
 avoid-c-arrays check

There are use cases where people need to diagnose also sugared types,
such as type aliases, decltypes or template parameter types, as use
of C-Style arrays in case their referenced type falls into such
category. Hence, we provide an opt-in option for clang-tidy's
modernize-avoid-c-arrays checker to acheive that, if desired.
---
 .../modernize/AvoidCArraysCheck.cpp           |  35 ++++-
 .../clang-tidy/modernize/AvoidCArraysCheck.h  |   1 +
 .../checks/modernize/avoid-c-arrays.rst       |   6 +
 .../avoid-c-arrays-check-sugared-types.cpp    | 126 ++++++++++++++++++
 4 files changed, 161 insertions(+), 7 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-check-sugared-types.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
index 0804aa76d953c..5a2997e19bdc2 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.cpp
@@ -21,12 +21,12 @@ AST_MATCHER(clang::TypeLoc, hasValidBeginLoc) {
   return Node.getBeginLoc().isValid();
 }
 
-AST_MATCHER_P(clang::TypeLoc, hasType,
-              clang::ast_matchers::internal::Matcher<clang::Type>,
-              InnerMatcher) {
+AST_MATCHER_P(clang::TypeLoc, hasArrayType, bool, CheckSugaredTypes) {
   const clang::Type *TypeNode = Node.getTypePtr();
-  return TypeNode != nullptr &&
-         InnerMatcher.matches(*TypeNode, Finder, Builder);
+  if (CheckSugaredTypes && TypeNode != nullptr) {
+    TypeNode = TypeNode->getUnqualifiedDesugaredType();
+  }
+  return TypeNode != nullptr && arrayType().matches(*TypeNode, Finder, 
Builder);
 }
 
 AST_MATCHER(clang::RecordDecl, isExternCContext) {
@@ -43,7 +43,8 @@ AST_MATCHER(clang::ParmVarDecl, isArgvOfMain) {
 
 AvoidCArraysCheck::AvoidCArraysCheck(StringRef Name, ClangTidyContext *Context)
     : ClangTidyCheck(Name, Context),
-      AllowStringArrays(Options.get("AllowStringArrays", false)) {}
+      AllowStringArrays(Options.get("AllowStringArrays", false)),
+      CheckSugaredTypes(Options.get("CheckSugaredTypes", false)) {}
 
 void AvoidCArraysCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
   Options.store(Opts, "AllowStringArrays", AllowStringArrays);
@@ -60,7 +61,7 @@ void AvoidCArraysCheck::registerMatchers(MatchFinder *Finder) 
{
                                          unless(parmVarDecl())))));
 
   Finder->addMatcher(
-      typeLoc(hasValidBeginLoc(), hasType(arrayType()),
+      typeLoc(hasValidBeginLoc(), hasArrayType(CheckSugaredTypes),
               optionally(hasParent(parmVarDecl().bind("param_decl"))),
               unless(anyOf(hasParent(parmVarDecl(isArgvOfMain())),
                            hasParent(varDecl(isExternC())),
@@ -96,6 +97,26 @@ void AvoidCArraysCheck::check(const MatchFinder::MatchResult 
&Result) {
   diag(ArrayType->getBeginLoc(),
        "do not declare %select{C-style|C VLA}0 arrays, use %1 instead")
       << IsVLA << llvm::join(RecommendTypes, " or ");
+
+  if (CheckSugaredTypes) {
+    PrintingPolicy PrintPolicy{getLangOpts()};
+    PrintPolicy.SuppressTagKeyword = true;
+
+    const auto TypeName = ArrayType->getType().getAsString(PrintPolicy);
+    const auto DesugaredTypeName = ArrayType->getType()
+                                       ->getUnqualifiedDesugaredType()
+                                       ->getCanonicalTypeInternal()
+                                       .getAsString(PrintPolicy);
+    if (TypeName != DesugaredTypeName) {
+      diag(ArrayType->getBeginLoc(), "declared type '%0' resolves to '%1'",
+           DiagnosticIDs::Note)
+          << TypeName << DesugaredTypeName;
+    } else {
+      diag(ArrayType->getBeginLoc(), "array type '%0' here",
+           DiagnosticIDs::Note)
+          << TypeName;
+    }
+  }
 }
 
 } // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h 
b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
index 719e88e4b3166..a22d656a78f33 100644
--- a/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/AvoidCArraysCheck.h
@@ -32,6 +32,7 @@ class AvoidCArraysCheck : public ClangTidyCheck {
 
 private:
   const bool AllowStringArrays;
+  const bool CheckSugaredTypes;
 };
 
 } // namespace clang::tidy::modernize
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 6a386ecd0fd4b..abd3037f18f05 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
@@ -72,3 +72,9 @@ can be either ``char* argv[]`` or ``char** argv``, but cannot 
be
   .. code:: c++
 
     const char name[] = "Some name";
+
+.. option:: CheckSugaredTypes
+
+  When set to `true` (default is `false`), type aliases, decltypes as well as
+  template parameter types will get resolved and diagnosed as usage of
+  C-style array in case their underlying type resolves to one.
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-check-sugared-types.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-check-sugared-types.cpp
new file mode 100644
index 0000000000000..e0de4ee811712
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/avoid-c-arrays-check-sugared-types.cpp
@@ -0,0 +1,126 @@
+// RUN: %check_clang_tidy -std=c++17 %s modernize-avoid-c-arrays %t -- \
+// RUN:  -config='{CheckOptions: { modernize-avoid-c-arrays.CheckSugaredTypes: 
true }}'
+
+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);
+  // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not declare C VLA arrays, 
use 'std::vector' instead
+  // CHECK-MESSAGES: :[[@LINE-2]]:13: note: declared type 'decltype(c)' 
resolves to 'int[b[0]]'
+
+  d e;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C VLA arrays, use 
'std::vector' instead
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: note: declared type 'd' resolves to 
'int[b[0]]'
+}
+
+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;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: do not declare C-style arrays, use 
'std::array' instead
+// CHECK-MESSAGES: :[[@LINE-2]]:7: note: declared type 'k' resolves to 'int[4]'
+
+template <typename T>
+class unique_ptr {
+  T *d;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not declare C-style arrays, 
use 'std::array' instead
+  // CHECK-MESSAGES: :[[@LINE-2]]:3: note: array type 'int[]' here
+
+  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;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not declare C-style arrays, 
use 'std::array' instead
+// CHECK-MESSAGES: :[[@LINE-2]]:12: note: declared type 'k2' resolves to 
'int[]'
+
+// 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];
+};
+}
+
+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' or 'std::vector' instead [modernize-avoid-c-arrays]
+
+using MyIntArray = int[10];
+// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: do not declare C-style arrays, 
use 'std::array' instead [modernize-avoid-c-arrays]
+
+using MyIntArray2D = MyIntArray[10];
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not declare C-style arrays, 
use 'std::array' instead [modernize-avoid-c-arrays]
+// CHECK-MESSAGES: :[[@LINE-2]]:22: note: declared type 'MyIntArray[10]' 
resolves to 'int[10][10]'
+
+using MyIntArray3D = MyIntArray2D[10];
+// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: do not declare C-style arrays, 
use 'std::array' instead [modernize-avoid-c-arrays]
+// CHECK-MESSAGES: :[[@LINE-2]]:22: note: declared type 'MyIntArray2D[10]' 
resolves to 'int[10][10][10]'
+
+MyIntArray3D array3D;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use 
'std::array' instead [modernize-avoid-c-arrays]
+// CHECK-MESSAGES: :[[@LINE-2]]:1: note: declared type 'MyIntArray3D' resolves 
to 'int[10][10][10]'
+
+MyIntArray2D array2D;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use 
'std::array' instead [modernize-avoid-c-arrays]
+// CHECK-MESSAGES: :[[@LINE-2]]:1: note: declared type 'MyIntArray2D' resolves 
to 'int[10][10]'
+
+MyIntArray array1D;
+// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not declare C-style arrays, use 
'std::array' instead [modernize-avoid-c-arrays]
+// CHECK-MESSAGES: :[[@LINE-2]]:1: note: declared type 'MyIntArray' resolves 
to 'int[10]'

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to