[clang-tools-extra] [clang-tidy] Support direct initialization in modernize smart pointer (PR #154732)
Liu Ke via cfe-commits
cfe-commits at lists.llvm.org
Sun Aug 24 23:49:43 PDT 2025
https://github.com/Sockke updated https://github.com/llvm/llvm-project/pull/154732
>From e7589f4a4b1a0dbc387020205746100ac21262a9 Mon Sep 17 00:00:00 2001
From: Sockke <liuke.gehry at bytedance.com>
Date: Thu, 21 Aug 2025 18:42:20 +0800
Subject: [PATCH 1/2] [clang-tidy] Support direct initialization in modernize
smart pointer
---
.../modernize/MakeSmartPtrCheck.cpp | 30 +++++++++++--------
.../checkers/modernize/make-shared.cpp | 2 ++
.../checkers/modernize/make-unique.cpp | 2 ++
3 files changed, 21 insertions(+), 13 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
index deef3586628c6..b4b235988da37 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -81,18 +81,16 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
auto IsPlacement = hasAnyPlacementArg(anything());
Finder->addMatcher(
- traverse(
- TK_AsIs,
- cxxBindTemporaryExpr(has(ignoringParenImpCasts(
- cxxConstructExpr(
- hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
- hasArgument(
- 0, cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
- equalsBoundNode(PointerType))))),
- CanCallCtor, unless(IsPlacement))
- .bind(NewExpression)),
- unless(isInTemplateInstantiation()))
- .bind(ConstructorCall))))),
+ traverse(TK_AsIs,
+ cxxConstructExpr(
+ hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
+ hasArgument(
+ 0, cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
+ equalsBoundNode(PointerType))))),
+ CanCallCtor, unless(IsPlacement))
+ .bind(NewExpression)),
+ unless(isInTemplateInstantiation()))
+ .bind(ConstructorCall)),
this);
Finder->addMatcher(
@@ -190,9 +188,15 @@ void MakeSmartPtrCheck::checkConstruct(SourceManager &SM, ASTContext *Ctx,
ConstructCallEnd = ConstructCallStart.getLocWithOffset(LAngle);
}
+ std::string FinalMakeSmartPtrFunctionName = MakeSmartPtrFunctionName.str();
+ auto Parents = Ctx->getParents(*Construct);
+ if (!Parents.empty() && Parents[0].get<clang::Decl>())
+ FinalMakeSmartPtrFunctionName =
+ ExprStr.str() + " = " + MakeSmartPtrFunctionName.str();
+
Diag << FixItHint::CreateReplacement(
CharSourceRange::getCharRange(ConstructCallStart, ConstructCallEnd),
- MakeSmartPtrFunctionName);
+ FinalMakeSmartPtrFunctionName);
// If the smart_ptr is built with brace enclosed direct initialization, use
// parenthesis instead.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-shared.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-shared.cpp
index e57f45c4127f9..65ece773b7c1f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-shared.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-shared.cpp
@@ -109,6 +109,8 @@ void basic() {
}
std::shared_ptr<int> R(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
+ // CHECK-FIXES: std::shared_ptr<int> R = std::make_shared<int>();
std::shared_ptr<int> S(new int);
// Create the shared_ptr as a parameter to a function.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp
index e665ca0a15a68..13103c735276a 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-unique.cpp
@@ -154,6 +154,8 @@ void basic() {
}
std::unique_ptr<int> R(new int());
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_unique instead
+ // CHECK-FIXES: std::unique_ptr<int> R = std::make_unique<int>();
std::unique_ptr<int> S(new int);
// Create the unique_ptr as a parameter to a function.
>From c1b401a03ccb3880311d9e9e7d7d08ad51897273 Mon Sep 17 00:00:00 2001
From: Sockke <liuke.gehry at bytedance.com>
Date: Mon, 25 Aug 2025 14:40:48 +0800
Subject: [PATCH 2/2] Cancel the wake-up of the parent AST.
---
.../clang-tidy/modernize/MakeSmartPtrCheck.cpp | 10 +++++++---
.../clang-tidy/modernize/MakeSmartPtrCheck.h | 4 ++--
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
index b4b235988da37..8ab3bca7da54a 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.cpp
@@ -19,6 +19,7 @@ namespace clang::tidy::modernize {
namespace {
constexpr char ConstructorCall[] = "constructorCall";
+constexpr char DirectVar[] = "directVar";
constexpr char ResetCall[] = "resetCall";
constexpr char NewExpression[] = "newExpression";
@@ -83,6 +84,8 @@ void MakeSmartPtrCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
Finder->addMatcher(
traverse(TK_AsIs,
cxxConstructExpr(
+ anyOf(hasParent(cxxBindTemporaryExpr()),
+ hasParent(varDecl().bind(DirectVar))),
hasType(getSmartPointerTypeMatcher()), argumentCountIs(1),
hasArgument(
0, cxxNewExpr(hasType(pointsTo(qualType(hasCanonicalType(
@@ -117,6 +120,7 @@ void MakeSmartPtrCheck::check(const MatchFinder::MatchResult &Result) {
SourceManager &SM = *Result.SourceManager;
const auto *Construct =
Result.Nodes.getNodeAs<CXXConstructExpr>(ConstructorCall);
+ const auto *DVar = Result.Nodes.getNodeAs<VarDecl>(DirectVar);
const auto *Reset = Result.Nodes.getNodeAs<CXXMemberCallExpr>(ResetCall);
const auto *Type = Result.Nodes.getNodeAs<QualType>(PointerType);
const auto *New = Result.Nodes.getNodeAs<CXXNewExpr>(NewExpression);
@@ -139,13 +143,14 @@ void MakeSmartPtrCheck::check(const MatchFinder::MatchResult &Result) {
if (!Initializes && IgnoreDefaultInitialization)
return;
if (Construct)
- checkConstruct(SM, Result.Context, Construct, Type, New);
+ checkConstruct(SM, Result.Context, Construct, DVar, Type, New);
else if (Reset)
checkReset(SM, Result.Context, Reset, New);
}
void MakeSmartPtrCheck::checkConstruct(SourceManager &SM, ASTContext *Ctx,
const CXXConstructExpr *Construct,
+ const VarDecl *DVar,
const QualType *Type,
const CXXNewExpr *New) {
SourceLocation ConstructCallStart = Construct->getExprLoc();
@@ -189,8 +194,7 @@ void MakeSmartPtrCheck::checkConstruct(SourceManager &SM, ASTContext *Ctx,
}
std::string FinalMakeSmartPtrFunctionName = MakeSmartPtrFunctionName.str();
- auto Parents = Ctx->getParents(*Construct);
- if (!Parents.empty() && Parents[0].get<clang::Decl>())
+ if (DVar)
FinalMakeSmartPtrFunctionName =
ExprStr.str() + " = " + MakeSmartPtrFunctionName.str();
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
index 02374dc06d9be..e2f9abed8138a 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/MakeSmartPtrCheck.h
@@ -51,8 +51,8 @@ class MakeSmartPtrCheck : public ClangTidyCheck {
const bool IgnoreDefaultInitialization;
void checkConstruct(SourceManager &SM, ASTContext *Ctx,
- const CXXConstructExpr *Construct, const QualType *Type,
- const CXXNewExpr *New);
+ const CXXConstructExpr *Construct, const VarDecl *DVar,
+ const QualType *Type, const CXXNewExpr *New);
void checkReset(SourceManager &SM, ASTContext *Ctx,
const CXXMemberCallExpr *Reset, const CXXNewExpr *New);
More information about the cfe-commits
mailing list