llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Styx (Shriya-Tyagi)

<details>
<summary>Changes</summary>

Adds the `modernize-use-shared-ptr-array` clang-tidy check.

The check detects `std::shared_ptr&lt;T&gt;` constructions managing arrays via
explicit array deleters and suggests replacing them with
`std::shared_ptr&lt;T[]&gt;` available since C++17.

Supported deleter forms include:
- `std::default_delete&lt;T[]&gt;`
- aliases of `std::default_delete&lt;T[]&gt;`
- captureless lambdas containing `delete[]`
- visible free-function deleters containing `delete[]`

Warn-only cases and unsupported patterns are documented in the check docs and 
covered by tests.

Fixes #<!-- -->180441.

---

Patch is 973.55 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/199458.diff


7 Files Affected:

- (modified) clang-tools-extra/clang-tidy/modernize/CMakeLists.txt (+1) 
- (modified) clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
(+3) 
- (added) clang-tools-extra/clang-tidy/modernize/UseSharedPtrArrayCheck.cpp 
(+527) 
- (added) clang-tools-extra/clang-tidy/modernize/UseSharedPtrArrayCheck.h (+47) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+6) 
- (added) 
clang-tools-extra/docs/clang-tidy/checks/modernize/use-shared-ptr-array.rst 
(+81) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-shared-ptr-array.cpp 
(+894) 


``````````diff
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 2c5c44db587fe..ad21bfd798648 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -46,6 +46,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   UseOverrideCheck.cpp
   UseRangesCheck.cpp
   UseScopedLockCheck.cpp
+  UseSharedPtrArrayCheck.cpp
   UseStartsEndsWithCheck.cpp
   UseStdBitCheck.cpp
   UseStdFormatCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index cc13da7535bcb..b56f078b35995 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -46,6 +46,7 @@
 #include "UseOverrideCheck.h"
 #include "UseRangesCheck.h"
 #include "UseScopedLockCheck.h"
+#include "UseSharedPtrArray.h"
 #include "UseStartsEndsWithCheck.h"
 #include "UseStdBitCheck.h"
 #include "UseStdFormatCheck.h"
@@ -95,6 +96,8 @@ class ModernizeModule : public ClangTidyModule {
     CheckFactories.registerCheck<UseRangesCheck>("modernize-use-ranges");
     CheckFactories.registerCheck<UseScopedLockCheck>(
         "modernize-use-scoped-lock");
+    CheckFactories.registerCheck<UseSharedPtrArray>(                           
                                                
+        "modernize-use-shared-ptr-array");   
     CheckFactories.registerCheck<UseStartsEndsWithCheck>(
         "modernize-use-starts-ends-with");
     CheckFactories.registerCheck<UseStdBitCheck>("modernize-use-std-bit");
diff --git a/clang-tools-extra/clang-tidy/modernize/UseSharedPtrArrayCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseSharedPtrArrayCheck.cpp
new file mode 100644
index 0000000000000..e24fe20ab7775
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseSharedPtrArrayCheck.cpp
@@ -0,0 +1,527 @@
+//===--- UseSharedPtrArrayCheck.cpp - clang-tidy 
--------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "UseSharedPtrArrayCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/TypeLoc.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+       void UseSharedPtrArrayCheck::registerMatchers(MatchFinder *Finder) {
+                 Finder->addMatcher(
+                             cxxConstructExpr(
+
+                                         hasType(qualType(hasDeclaration(
+                                                             
classTemplateSpecializationDecl(hasName("::std::shared_ptr"))))),
+
+                                                                       
argumentCountIs(2),
+
+                                                                               
  hasArgument(
+                                                                               
                      0, 
ignoringParenImpCasts(cxxNewExpr(isArray()).bind("newExpr"))),
+
+                                                                               
                                anyOf(hasArgument(
+                                                                               
                                                            1, ignoringImplicit(
+                                                                               
                                                                                
           cxxConstructExpr(
+                                                                               
                                                                                
                                               
hasType(qualType(hasCanonicalType(hasDeclaration(
+                                                                               
                                                                                
                                                                                
   classTemplateSpecializationDecl(
+                                                                               
                                                                                
                                                                                
                                               
hasName("::std::default_delete")))))))
+                                                                               
                                                                                
                                                                                
                                                                              
.bind("defaultDelete"))),
+
+                                                                               
                                                                                
                                                                                
                                                                                
              hasArgument(
+                                                                               
                                                                                
                                                                                
                                                                                
                                    1, 
ignoringImplicit(lambdaExpr().bind("lambdaDeleter"))),
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                    hasArgument(1, 
ignoringImplicit(declRefExpr(to(
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
           functionDecl().bind("deleterFunction")))))))
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                     .bind("sharedPtrCtor"),
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                           this);
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                           }
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                           // Verifies that a callable body consists of exactly 
delete[] param; with only
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                           // one parameter. Used for both lambdas and free 
functions.
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                           static bool BodyIsArrayDeleteOfParam(const Stmt 
*Body,
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                const 
ParmVarDecl *Param) {
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                          const 
auto *Compound = dyn_cast_or_null<CompoundStmt>(Body);
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                            if 
(!Compound || Compound->size() != 1)
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
return false;
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
  const auto *OnlyExpr = dyn_cast<Expr>(Compound->body_front());
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
    if (!OnlyExpr)
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
        return false;
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
          OnlyExpr = OnlyExpr->IgnoreParenImpCasts();
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
            const auto *DelExpr = dyn_cast<CXXDeleteExpr>(OnlyExpr);
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
              if (!DelExpr || !DelExpr->isArrayForm())
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                  return false;
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                    const auto *DRE =
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                          
dyn_cast<DeclRefExpr>(DelExpr->getArgument()->IgnoreParenImpCasts());
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                            if (!DRE)
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                return false;
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                  return DRE->getDecl() == Param;
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                  }
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                  // Manual parent walk rather than a matcher 
because implicit
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                  // wrappers obscure assignment contexts.
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                  static const VarDecl 
*FindParentVarDecl(ASTContext &Ctx, const Stmt *S) {
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                          DynTypedNode Node = 
DynTypedNode::create(*S);
+
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                            for (;;) {
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                    auto Parents = 
Ctx.getParents(Node);
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                                                
                                                        if (Parents.empty())
+                                                                               
                                                                                
                                                                                
                                                                                
                                                                                
                                                 ...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/199458
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to