[clang-tools-extra] WIP: [clang-tidy] Add SmartPtrName to MakeSmartPtrCheck for flexible … (PR #117529)
Helmut Januschka via cfe-commits
cfe-commits at lists.llvm.org
Mon Nov 25 02:41:07 PST 2024
https://github.com/hjanuschka updated https://github.com/llvm/llvm-project/pull/117529
>From 9466fb73adfb050e9eac426459c18a7a5bca1982 Mon Sep 17 00:00:00 2001
From: Helmut Januschka <helmut at januschka.com>
Date: Mon, 25 Nov 2024 09:59:21 +0100
Subject: [PATCH 1/2] WIP: [clang-tidy] Add SmartPtrName to MakeSmartPtrCheck
for flexible type matching
Introduced a `SmartPtrName` field in `MakeSmartPtrCheck` to allow matching on other smart pointer types, such as `base::scoped_refptr`, in addition to `std::shared_ptr`. This enables more versatile usage of the check without duplicating matcher logic.
---
clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.cpp | 5 +++--
clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.h | 3 +++
.../clang-tidy/modernize/MakeSmartPtrCheck.cpp | 6 +++---
clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h | 1 +
.../docs/clang-tidy/checks/modernize/make-shared.rst | 6 ++++++
5 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.cpp
index 69f7d9f69eeed0..34009046fec6ae 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.cpp
@@ -16,13 +16,14 @@ using namespace clang::ast_matchers;
namespace clang::tidy::modernize {
MakeSharedCheck::MakeSharedCheck(StringRef Name, ClangTidyContext *Context)
- : MakeSmartPtrCheck(Name, Context, "std::make_shared") {}
+ : MakeSmartPtrCheck(Name, Context, "std::make_shared"),
+ MakeSmartPtrType(Options.get("MakeSmartPtrType", "::std::shared_ptr")) {}
MakeSharedCheck::SmartPtrTypeMatcher
MakeSharedCheck::getSmartPointerTypeMatcher() const {
return qualType(hasUnqualifiedDesugaredType(
recordType(hasDeclaration(classTemplateSpecializationDecl(
- hasName("::std::shared_ptr"), templateArgumentCountIs(1),
+ hasName(MakeSmartPtrType), templateArgumentCountIs(1),
hasTemplateArgument(0, templateArgument(refersToType(
qualType().bind(PointerType)))))))));
}
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.h b/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.h
index caaf4ae403c34f..932796e3a147f1 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/MakeSharedCheck.h
@@ -26,6 +26,9 @@ namespace clang::tidy::modernize {
/// For the user-facing documentation see:
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/make-shared.html
class MakeSharedCheck : public MakeSmartPtrCheck {
+private:
+ const StringRef MakeSmartPtrType;
+
public:
MakeSharedCheck(StringRef Name, ClangTidyContext *Context);
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
index d1d7e9dcfa9c0d..3f77e6727d19f8 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -46,6 +46,7 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
areDiagsSelfContained()),
MakeSmartPtrFunctionHeader(
Options.get("MakeSmartPtrFunctionHeader", "<memory>")),
+ MakeSmartPtrType(Options.get("MakeSmartPtrType", "::std::shared_ptr")),
MakeSmartPtrFunctionName(
Options.get("MakeSmartPtrFunction", MakeSmartPtrFunctionName)),
IgnoreMacros(Options.getLocalOrGlobal("IgnoreMacros", true)),
@@ -55,6 +56,7 @@ MakeSmartPtrCheck::MakeSmartPtrCheck(StringRef Name, ClangTidyContext *Context,
void MakeSmartPtrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "IncludeStyle", Inserter.getStyle());
Options.store(Opts, "MakeSmartPtrFunctionHeader", MakeSmartPtrFunctionHeader);
+ Options.store(Opts, "MakeSmartPtrType", MakeSmartPtrType);
Options.store(Opts, "MakeSmartPtrFunction", MakeSmartPtrFunctionName);
Options.store(Opts, "IgnoreMacros", IgnoreMacros);
Options.store(Opts, "IgnoreDefaultInitialization",
@@ -115,7 +117,6 @@ void MakeSmartPtrCheck::check(const MatchFinder::MatchResult &Result) {
// 'smart_ptr' refers to 'std::shared_ptr' or 'std::unique_ptr' or other
// pointer, 'make_smart_ptr' refers to 'std::make_shared' or
// 'std::make_unique' or other function that creates smart_ptr.
-
SourceManager &SM = *Result.SourceManager;
const auto *Construct =
Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructorCall);
@@ -361,8 +362,7 @@ bool MakeSmartPtrCheck::replaceNew(DiagnosticBuilder &Diag,
Diag << FixItHint::CreateRemoval(
SourceRange(NewStart, InitRange.getBegin()));
Diag << FixItHint::CreateRemoval(SourceRange(InitRange.getEnd(), NewEnd));
- }
- else {
+ } else {
// New array expression with default/value initialization:
// smart_ptr<Foo[]>(new int[5]());
// smart_ptr<Foo[]>(new Foo[5]());
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
index 02374dc06d9be5..c4b407e5090656 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
@@ -46,6 +46,7 @@ class MakeSmartPtrCheck : public ClangTidyCheck {
private:
utils::IncludeInserter Inserter;
const StringRef MakeSmartPtrFunctionHeader;
+ const StringRef MakeSmartPtrType;
const StringRef MakeSmartPtrFunctionName;
const bool IgnoreMacros;
const bool IgnoreDefaultInitialization;
diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/make-shared.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/make-shared.rst
index 9c1fceaa060002..31d3de7a7893f3 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/modernize/make-shared.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/make-shared.rst
@@ -39,6 +39,12 @@ Options
A string specifying the corresponding header of make-shared-ptr function.
Default is `memory`.
+
+.. option:: MakeSmartPtrType
+
+ A string specifying the corresponding pointer type.
+ Default is `::std::shared_ptr`.
+
.. option:: IncludeStyle
A string specifying which include-style is used, `llvm` or `google`. Default
>From bf9292eb4f758ba22feedf56a3de47e8234ca3d2 Mon Sep 17 00:00:00 2001
From: Helmut Januschka <helmut at januschka.com>
Date: Mon, 25 Nov 2024 11:40:50 +0100
Subject: [PATCH 2/2] up
---
.../modernize/make-shared-ptr-name.cpp | 142 ++++++++++++++++++
1 file changed, 142 insertions(+)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/make-shared-ptr-name.cpp
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-shared-ptr-name.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-shared-ptr-name.cpp
new file mode 100644
index 00000000000000..0be12a47c0db41
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-shared-ptr-name.cpp
@@ -0,0 +1,142 @@
+// RUN: %check_clang_tidy %s modernize-make-shared %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-make-shared.MakeSmartPtrType, value: '::base::scoped_refptr'}, \
+// RUN: {key: modernize-make-shared.MakeSmartPtrFunction, value: 'base::MakeRefCounted'}]}" \
+// RUN: -- -std=c++11 -nostdinc++
+
+namespace base {
+
+using nullptr_t = decltype(nullptr);
+
+template <typename T>
+struct remove_extent { typedef T type; };
+
+template <typename T>
+struct remove_reference { typedef T type; };
+
+template <typename T>
+class scoped_refptr {
+public:
+ typedef T element_type;
+ typedef T* pointer;
+ typedef element_type& reference;
+
+ // Default constructors
+ constexpr scoped_refptr() noexcept : ptr_(nullptr) {}
+ constexpr scoped_refptr(nullptr_t) noexcept : ptr_(nullptr) {}
+
+ // Constructors from raw pointer
+ explicit scoped_refptr(T* p) noexcept : ptr_(p) {}
+ scoped_refptr(T* p, bool) noexcept : ptr_(p) {} // Special constructor for temporaries
+
+ // Copy constructors
+ scoped_refptr(const scoped_refptr& r) noexcept : ptr_(r.ptr_) {}
+ template<typename U>
+ scoped_refptr(const scoped_refptr<U>& r) noexcept : ptr_(r.get()) {}
+
+ // Move constructors
+ scoped_refptr(scoped_refptr&& r) noexcept : ptr_(r.ptr_) {
+ r.ptr_ = nullptr;
+ }
+ template<typename U>
+ scoped_refptr(scoped_refptr<U>&& r) noexcept : ptr_(r.get()) {
+ r.reset();
+ }
+
+ // Assignment operators
+ scoped_refptr& operator=(const scoped_refptr& r) noexcept {
+ ptr_ = r.ptr_;
+ return *this;
+ }
+ template<typename U>
+ scoped_refptr& operator=(const scoped_refptr<U>& r) noexcept {
+ ptr_ = r.get();
+ return *this;
+ }
+
+ scoped_refptr& operator=(scoped_refptr&& r) noexcept {
+ ptr_ = r.ptr_;
+ r.ptr_ = nullptr;
+ return *this;
+ }
+ template<typename U>
+ scoped_refptr& operator=(scoped_refptr<U>&& r) noexcept {
+ ptr_ = r.get();
+ r.reset();
+ return *this;
+ }
+
+ void reset(T* p = nullptr) noexcept {
+ ptr_ = p;
+ }
+
+ void swap(scoped_refptr& r) noexcept {
+ T* tmp = ptr_;
+ ptr_ = r.ptr_;
+ r.ptr_ = tmp;
+ }
+
+ // Observers
+ T* get() const noexcept { return ptr_; }
+ T& operator*() const noexcept { return *ptr_; }
+ T* operator->() const noexcept { return ptr_; }
+ explicit operator bool() const noexcept { return ptr_ != nullptr; }
+
+ ~scoped_refptr() { }
+
+private:
+ element_type* ptr_;
+};
+
+// Non-member functions
+template<class T>
+void swap(scoped_refptr<T>& a, scoped_refptr<T>& b) noexcept {
+ a.swap(b);
+}
+
+template<class T, class U>
+bool operator==(const scoped_refptr<T>& a, const scoped_refptr<U>& b) noexcept {
+ return a.get() == b.get();
+}
+
+template<class T>
+bool operator==(const scoped_refptr<T>& a, nullptr_t) noexcept {
+ return !a;
+}
+
+template <typename T, typename... Args>
+scoped_refptr<T> MakeRefCounted(Args&&... args) {
+ return scoped_refptr<T>(new T(args...));
+}
+
+} // namespace base
+
+struct Base {
+ Base() {}
+ Base(int, int) {}
+};
+
+struct Derived : public Base {
+ Derived() {}
+ Derived(int, int) : Base(0, 0) {}
+};
+
+void basic() {
+ // Direct constructor calls - not covered by this check
+ base::scoped_refptr<int> P1(new int());
+ base::scoped_refptr<Base> basePtr(new Base());
+
+ // Reset calls
+ P1.reset(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use base::MakeRefCounted instead
+ // CHECK-FIXES: P1 = base::MakeRefCounted<int>();
+
+ basePtr.reset(new Derived());
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use base::MakeRefCounted instead
+ // CHECK-FIXES: basePtr = base::MakeRefCounted<Derived>();
+}
+
+base::scoped_refptr<Base> factory() {
+ return base::scoped_refptr<Base>(new Base);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use base::MakeRefCounted instead
+ // CHECK-FIXES: return base::MakeRefCounted<Base>();
+}
\ No newline at end of file
More information about the cfe-commits
mailing list