https://github.com/hjanuschka created
https://github.com/llvm/llvm-project/pull/118120
Adds a new check that converts std::make_* function calls to direct constructor
calls using CTAD. Transforms make_optional, make_unique, make_shared and
make_pair into their equivalent direct constructor calls, leveraging C++17's
class template argument deduction.
>From 2bcf868d023b5be2f3c88f1d68dd2084b7db4604 Mon Sep 17 00:00:00 2001
From: Helmut Januschka
Date: Fri, 29 Nov 2024 19:17:36 +0100
Subject: [PATCH] [clang-tidy] Add modernize-make-direct check
Adds a new check that converts std::make_* function calls to direct constructor
calls using CTAD. Transforms make_optional, make_unique, make_shared and
make_pair
into their equivalent direct constructor calls, leveraging C++17's class
template
argument deduction.
---
.../clang-tidy/modernize/CMakeLists.txt | 1 +
.../modernize/MakeFunctionToDirectCheck.cpp | 108 ++
.../modernize/MakeFunctionToDirectCheck.h | 20
.../modernize/ModernizeTidyModule.cpp | 3 +
clang-tools-extra/docs/ReleaseNotes.rst | 6 +
.../modernize/modernize-make-direct.rst | 17 +++
.../checkers/modernize/make-direct-check.cpp | 66 +++
7 files changed, 221 insertions(+)
create mode 100644
clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
create mode 100644
clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h
create mode 100644
clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
create mode 100644
clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index c919d49b42873a..7e8d9296c6a64c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -49,6 +49,7 @@ add_clang_library(clangTidyModernizeModule STATIC
UseTransparentFunctorsCheck.cpp
UseUncaughtExceptionsCheck.cpp
UseUsingCheck.cpp
+ MakeFunctionToDirectCheck.cpp
LINK_LIBS
clangTidy
diff --git
a/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
new file mode 100644
index 00..0262f77f4992cb
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
@@ -0,0 +1,108 @@
+#include "MakeFunctionToDirectCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Type.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+void MakeFunctionToDirectCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus17)
+return;
+ // Match make_xxx function calls
+ Finder->addMatcher(callExpr(callee(functionDecl(hasAnyName(
+ "std::make_optional", "std::make_unique",
+ "std::make_shared", "std::make_pair"
+ .bind("make_call"),
+ this);
+}
+
+bool MakeFunctionToDirectCheck::isMakeFunction(
+const std::string &FuncName) const {
+ static const std::array MakeFuncs = {
+ "make_optional", "make_unique", "make_shared", "make_pair"};
+
+ return std::any_of(MakeFuncs.begin(), MakeFuncs.end(),
+ [&](const auto &Prefix) {
+ return FuncName.find(Prefix) != std::string::npos;
+ });
+}
+
+std::string MakeFunctionToDirectCheck::getTemplateType(
+const CXXConstructExpr *Construct) const {
+ if (!Construct)
+return {};
+
+ const auto *RecordType =
+ dyn_cast(Construct->getType().getTypePtr());
+ if (!RecordType)
+return {};
+
+ return RecordType->getDecl()->getNameAsString();
+}
+
+void MakeFunctionToDirectCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Call = Result.Nodes.getNodeAs("make_call");
+ if (!Call)
+return;
+
+ const auto *FuncDecl = dyn_cast(Call->getCalleeDecl());
+ if (!FuncDecl || !FuncDecl->getTemplateSpecializationArgs())
+return;
+
+ std::string FuncName = FuncDecl->getNameAsString();
+ if (!isMakeFunction(FuncName))
+return;
+
+ std::string Args;
+ if (Call->getNumArgs() > 0) {
+SourceRange ArgRange(Call->getArg(0)->getBeginLoc(),
+ Call->getArg(Call->getNumArgs() - 1)->getEndLoc());
+Args = std::string(Lexer::getSourceText(
+CharSourceRange::getTokenRange(ArgRange), *Result.SourceManager,
+Result.Context->getLangOpts()));
+ }
+
+ std::string Replacement;
+ if (FuncName == "make_unique" || FuncName == "make_shared") {
+const auto *TemplateArgs = FuncDecl->getTemplateSpecializationArgs();
+if (!TemplateArgs || TemplateArgs->size() == 0)
+ return;
+
+QualType Type = T