https://github.com/hjanuschka updated 
https://github.com/llvm/llvm-project/pull/118120

>From c741fffc1aa978e39946bb34efc455dc9333f993 Mon Sep 17 00:00:00 2001
From: Helmut Januschka <hel...@januschka.com>
Date: Fri, 29 Nov 2024 19:17:36 +0100
Subject: [PATCH 1/3] [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 bab1167fb15ff..56273f914178b 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -50,6 +50,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 0000000000000..0262f77f4992c
--- /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<std::string_view, 4> 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<clang::RecordType>(Construct->getType().getTypePtr());
+  if (!RecordType)
+    return {};
+
+  return RecordType->getDecl()->getNameAsString();
+}
+
+void MakeFunctionToDirectCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("make_call");
+  if (!Call)
+    return;
+
+  const auto *FuncDecl = dyn_cast<FunctionDecl>(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 = TemplateArgs->get(0).getAsType();
+    PrintingPolicy Policy(Result.Context->getLangOpts());
+    Policy.SuppressTagKeyword = true;
+    std::string TypeStr = Type.getAsString(Policy);
+
+    std::string SmartPtr =
+        (FuncName == "make_unique") ? "unique_ptr" : "shared_ptr";
+    Replacement = "std::" + SmartPtr + "(new " + TypeStr + "(" + Args + "))";
+  } else {
+    std::string TemplateType;
+    if (FuncName == "make_optional")
+      TemplateType = "std::optional";
+    else if (FuncName == "make_shared")
+      TemplateType = "std::shared_ptr";
+    else if (FuncName == "make_pair")
+      TemplateType = "std::pair";
+
+    if (TemplateType.empty())
+      return;
+
+    Replacement = TemplateType + "(" + Args + ")";
+  }
+
+  if (!Replacement.empty()) {
+    diag(Call->getBeginLoc(),
+         "use class template argument deduction (CTAD) instead of %0")
+        << FuncName
+        << FixItHint::CreateReplacement(
+               CharSourceRange::getTokenRange(Call->getSourceRange()),
+               Replacement);
+  }
+}
+
+} // namespace clang::tidy::modernize
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h 
b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h
new file mode 100644
index 0000000000000..0fb786e827a71
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h
@@ -0,0 +1,20 @@
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::modernize {
+
+class MakeFunctionToDirectCheck : public ClangTidyCheck {
+public:
+  MakeFunctionToDirectCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  // Helper to check if the call is a make_xxx function
+  bool isMakeFunction(const std::string &FuncName) const;
+  // Get the template type from make_xxx call
+  std::string getTemplateType(const CXXConstructExpr *Construct) const;
+};
+
+} // namespace clang::tidy::modernize
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index e872759856f3c..e38340bb66789 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -16,6 +16,7 @@
 #include "DeprecatedIosBaseAliasesCheck.h"
 #include "LoopConvertCheck.h"
 #include "MacroToEnumCheck.h"
+#include "MakeFunctionToDirectCheck.h"
 #include "MakeSharedCheck.h"
 #include "MakeUniqueCheck.h"
 #include "MinMaxUseInitializerListCheck.h"
@@ -125,6 +126,8 @@ class ModernizeModule : public ClangTidyModule {
     CheckFactories.registerCheck<UseUncaughtExceptionsCheck>(
         "modernize-use-uncaught-exceptions");
     CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using");
+    CheckFactories.registerCheck<MakeFunctionToDirectCheck>(
+    "modernize-make-direct");
   }
 };
 
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 882ee0015df17..e5c1d4d107aba 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -124,6 +124,12 @@ New checks
   pointer and store it as class members without handle the copy and move
   constructors and the assignments.
 
+- New :doc:`modernize-make-direct <clang-tidy/checks/modernize/make-direct>` 
check.
+
+  Converts std::make_* function calls to direct constructor calls using CTAD.
+  Transforms make_optional, make_unique, make_shared and make_pair into 
equivalent 
+  direct constructor calls using C++17's class template argument deduction.
+
 - New :doc:`bugprone-misleading-setter-of-reference
   <clang-tidy/checks/bugprone/misleading-setter-of-reference>` check.
 
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
new file mode 100644
index 0000000000000..6860ff39c514c
--- /dev/null
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
@@ -0,0 +1,17 @@
+.. title:: clang-tidy - modernize-make-direct
+
+modernize-make-direct
+====================
+
+Replaces ``std::make_*`` function calls with direct constructor calls using 
class template
+argument deduction (CTAD).
+
+================================== ====================================
+  Before                             After
+---------------------------------- ------------------------------------
+``std::make_optional<int>(42)``    ``std::optional(42)``
+``std::make_unique<Widget>(1)``    ``std::unique_ptr(new Widget(1))``
+``std::make_shared<Widget>(2)``    ``std::shared_ptr(new Widget(2))``
+``std::make_pair(1, "test")``      ``std::pair(1, "test")``
+================================== ====================================
+
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp
new file mode 100644
index 0000000000000..db3e4fe1cb4ff
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp
@@ -0,0 +1,66 @@
+// RUN: %check_clang_tidy %s modernize-make-direct %t
+
+namespace std {
+template<typename T>
+struct optional { 
+ optional(const T&) {} 
+};
+
+template<typename T> 
+optional<T> make_optional(const T& t) { return optional<T>(t); }
+
+template<typename T>
+struct unique_ptr {
+ explicit unique_ptr(T*) {}
+};
+
+template<typename T, typename... Args>
+unique_ptr<T> make_unique(Args&&... args) { 
+ return unique_ptr<T>(new T(args...));
+}
+
+template<typename T>
+struct shared_ptr {
+ shared_ptr(T*) {}
+};
+
+template<typename T, typename... Args>
+shared_ptr<T> make_shared(Args&&... args) {
+ return shared_ptr<T>(new T(args...));
+}
+
+template<typename T, typename U>
+struct pair {
+ T first;
+ U second;
+ pair(const T& x, const U& y) : first(x), second(y) {}
+};
+
+template<typename T, typename U>
+pair<T,U> make_pair(T&& t, U&& u) { 
+ return pair<T,U>(t, u); 
+}
+}
+
+struct Widget {
+ Widget(int x) {}
+};
+
+
+void basic_tests() {
+ auto o1 = std::make_optional<int>(42);
+ // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of make_optional [modernize-make-direct]
+ // CHECK-FIXES: auto o1 = std::optional(42);
+
+  auto u1 = std::make_unique<Widget>(1);
+ // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of make_unique [modernize-make-direct]
+ // CHECK-FIXES: auto u1 = std::unique_ptr(new Widget(1));
+
+ auto s1 = std::make_shared<Widget>(2);
+  // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of make_shared
+  // CHECK-FIXES: auto s1 = std::shared_ptr(new Widget(2));
+
+  auto p1 = std::make_pair(1, "test");
+  // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of make_pair
+  // CHECK-FIXES: auto p1 = std::pair(1, "test");
+}

>From ccfe7ffc48b7efa779ab305f738343444b62cf94 Mon Sep 17 00:00:00 2001
From: Helmut Januschka <hel...@januschka.com>
Date: Tue, 10 Jun 2025 21:43:22 +0200
Subject: [PATCH 2/3] Address PR feedback and refactor to
 TransformerClangTidyCheck

- Refactor implementation to use TransformerClangTidyCheck for cleaner code
- Remove make_unique and make_shared transformations to avoid conflicts and new 
usage
- Add configuration options: CheckMakePair, CheckMakeOptional, CheckMakeTuple
- Add support for std::make_tuple transformations
- Update documentation with options and warnings about smart pointer functions
- Fix clang-format issues in ModernizeTidyModule.cpp
- Add C++17 requirement enforcement with proper test setup
- All tests passing with correct CTAD transformations
---
 .../modernize/MakeFunctionToDirectCheck.cpp   | 151 +++++++-----------
 .../modernize/MakeFunctionToDirectCheck.h     |  41 +++--
 .../modernize/ModernizeTidyModule.cpp         |   2 +-
 clang-tools-extra/docs/ReleaseNotes.rst       |   2 +-
 .../modernize/modernize-make-direct.rst       |  33 +++-
 .../checkers/modernize/make-direct-check.cpp  |  32 ++--
 6 files changed, 143 insertions(+), 118 deletions(-)

diff --git 
a/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
index 0262f77f4992c..395a9a500edd1 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
@@ -1,108 +1,75 @@
+//===--- MakeFunctionToDirectCheck.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 "MakeFunctionToDirectCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Type.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "../utils/TransformerClangTidyCheck.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/Transformer/RangeSelector.h"
+#include "clang/Tooling/Transformer/RewriteRule.h"
+#include "clang/Tooling/Transformer/Stencil.h"
 
-using namespace clang::ast_matchers;
+using namespace ::clang::ast_matchers;
+using namespace ::clang::transformer;
 
 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<std::string_view, 4> 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<clang::RecordType>(Construct->getType().getTypePtr());
-  if (!RecordType)
-    return {};
-
-  return RecordType->getDecl()->getNameAsString();
-}
-
-void MakeFunctionToDirectCheck::check(const MatchFinder::MatchResult &Result) {
-  const auto *Call = Result.Nodes.getNodeAs<CallExpr>("make_call");
-  if (!Call)
-    return;
-
-  const auto *FuncDecl = dyn_cast<FunctionDecl>(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()));
+namespace {
+
+RewriteRuleWith<std::string> makeFunctionToDirectCheckImpl(
+    bool CheckMakePair, bool CheckMakeOptional, bool CheckMakeTuple) {
+  std::vector<RewriteRuleWith<std::string>> Rules;
+
+  // Helper to create a rule for a specific make_* function
+  auto createRule = [](StringRef MakeFunction, StringRef DirectType) {
+    auto WarningMessage = cat("use class template argument deduction (CTAD) "
+                              "instead of ", MakeFunction);
+
+    return makeRule(
+        callExpr(callee(functionDecl(hasName(MakeFunction))),
+                 unless(hasParent(implicitCastExpr(
+                     hasImplicitDestinationType(qualType(hasCanonicalType(
+                         qualType(asString("void")))))))))
+            .bind("make_call"),
+        changeTo(node("make_call"), cat(DirectType, "(", 
callArgs("make_call"), ")")),
+        WarningMessage);
+  };
+
+  if (CheckMakeOptional) {
+    Rules.push_back(createRule("std::make_optional", "std::optional"));
   }
 
-  std::string Replacement;
-  if (FuncName == "make_unique" || FuncName == "make_shared") {
-    const auto *TemplateArgs = FuncDecl->getTemplateSpecializationArgs();
-    if (!TemplateArgs || TemplateArgs->size() == 0)
-      return;
+  if (CheckMakePair) {
+    Rules.push_back(createRule("std::make_pair", "std::pair"));
+  }
 
-    QualType Type = TemplateArgs->get(0).getAsType();
-    PrintingPolicy Policy(Result.Context->getLangOpts());
-    Policy.SuppressTagKeyword = true;
-    std::string TypeStr = Type.getAsString(Policy);
+  if (CheckMakeTuple) {
+    Rules.push_back(createRule("std::make_tuple", "std::tuple"));
+  }
 
-    std::string SmartPtr =
-        (FuncName == "make_unique") ? "unique_ptr" : "shared_ptr";
-    Replacement = "std::" + SmartPtr + "(new " + TypeStr + "(" + Args + "))";
-  } else {
-    std::string TemplateType;
-    if (FuncName == "make_optional")
-      TemplateType = "std::optional";
-    else if (FuncName == "make_shared")
-      TemplateType = "std::shared_ptr";
-    else if (FuncName == "make_pair")
-      TemplateType = "std::pair";
+  return applyFirst(Rules);
+}
 
-    if (TemplateType.empty())
-      return;
+} // namespace
 
-    Replacement = TemplateType + "(" + Args + ")";
-  }
+MakeFunctionToDirectCheck::MakeFunctionToDirectCheck(StringRef Name,
+                                                     ClangTidyContext *Context)
+    : utils::TransformerClangTidyCheck(Name, Context),
+      CheckMakePair(Options.get("CheckMakePair", true)),
+      CheckMakeOptional(Options.get("CheckMakeOptional", true)),
+      CheckMakeTuple(Options.get("CheckMakeTuple", true)) {
+  setRule(makeFunctionToDirectCheckImpl(CheckMakePair, CheckMakeOptional, 
CheckMakeTuple));
+}
 
-  if (!Replacement.empty()) {
-    diag(Call->getBeginLoc(),
-         "use class template argument deduction (CTAD) instead of %0")
-        << FuncName
-        << FixItHint::CreateReplacement(
-               CharSourceRange::getTokenRange(Call->getSourceRange()),
-               Replacement);
-  }
+void MakeFunctionToDirectCheck::storeOptions(
+    ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "CheckMakePair", CheckMakePair);
+  Options.store(Opts, "CheckMakeOptional", CheckMakeOptional);
+  Options.store(Opts, "CheckMakeTuple", CheckMakeTuple);
 }
 
 } // namespace clang::tidy::modernize
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h 
b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h
index 0fb786e827a71..c3637b2bc00dc 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h
+++ b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h
@@ -1,20 +1,39 @@
-#include "../ClangTidyCheck.h"
+//===--- MakeFunctionToDirectCheck.h - clang-tidy --------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKEFUNCTIONTODIRECTCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKEFUNCTIONTODIRECTCHECK_H
+
+#include "../utils/TransformerClangTidyCheck.h"
 
 namespace clang::tidy::modernize {
 
-class MakeFunctionToDirectCheck : public ClangTidyCheck {
+/// Converts std::make_* function calls to direct constructor calls using
+/// class template argument deduction (CTAD).
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/make-direct.html
+class MakeFunctionToDirectCheck : public utils::TransformerClangTidyCheck {
 public:
-  MakeFunctionToDirectCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+  MakeFunctionToDirectCheck(StringRef Name, ClangTidyContext *Context);
 
-  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
-  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus17;
+  }
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
 
 private:
-  // Helper to check if the call is a make_xxx function
-  bool isMakeFunction(const std::string &FuncName) const;
-  // Get the template type from make_xxx call
-  std::string getTemplateType(const CXXConstructExpr *Construct) const;
+  const bool CheckMakePair;
+  const bool CheckMakeOptional;
+  const bool CheckMakeTuple;
 };
 
-} // namespace clang::tidy::modernize
\ No newline at end of file
+} // namespace clang::tidy::modernize
+
+#endif // 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_MAKEFUNCTIONTODIRECTCHECK_H
\ No newline at end of file
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index e38340bb66789..4c6964a729346 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -127,7 +127,7 @@ class ModernizeModule : public ClangTidyModule {
         "modernize-use-uncaught-exceptions");
     CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using");
     CheckFactories.registerCheck<MakeFunctionToDirectCheck>(
-    "modernize-make-direct");
+        "modernize-make-direct");
   }
 };
 
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index e5c1d4d107aba..8917627b13ea0 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -127,7 +127,7 @@ New checks
 - New :doc:`modernize-make-direct <clang-tidy/checks/modernize/make-direct>` 
check.
 
   Converts std::make_* function calls to direct constructor calls using CTAD.
-  Transforms make_optional, make_unique, make_shared and make_pair into 
equivalent 
+  Transforms make_optional, make_pair, and make_tuple into equivalent 
   direct constructor calls using C++17's class template argument deduction.
 
 - New :doc:`bugprone-misleading-setter-of-reference
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
index 6860ff39c514c..c11a9b66bdb22 100644
--- 
a/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
@@ -10,8 +10,37 @@ argument deduction (CTAD).
   Before                             After
 ---------------------------------- ------------------------------------
 ``std::make_optional<int>(42)``    ``std::optional(42)``
-``std::make_unique<Widget>(1)``    ``std::unique_ptr(new Widget(1))``
-``std::make_shared<Widget>(2)``    ``std::shared_ptr(new Widget(2))``
 ``std::make_pair(1, "test")``      ``std::pair(1, "test")``
+``std::make_tuple(1, 2.0, "hi")``  ``std::tuple(1, 2.0, "hi")``
 ================================== ====================================
 
+.. note::
+
+   This check does not transform ``std::make_unique`` or ``std::make_shared`` 
because:
+   
+   1. These smart pointer types cannot be constructed using CTAD from raw 
pointers.
+   2. ``std::make_shared`` provides performance benefits (single allocation) 
and 
+      exception safety that would be lost with direct construction.
+   3. Direct use of ``new`` is discouraged in modern C++ code.
+   
+   Use the dedicated ``modernize-make-unique`` and ``modernize-make-shared`` 
checks
+   for transforming these functions.
+
+Options
+-------
+
+.. option:: CheckMakePair
+
+   When `true`, transforms ``std::make_pair`` calls to direct constructor 
calls.
+   Default is `true`.
+
+.. option:: CheckMakeOptional
+
+   When `true`, transforms ``std::make_optional`` calls to direct constructor 
calls.
+   Default is `true`.
+
+.. option:: CheckMakeTuple
+
+   When `true`, transforms ``std::make_tuple`` calls to direct constructor 
calls.
+   Default is `true`.
+
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp
index db3e4fe1cb4ff..2a1fe4713ecb9 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s modernize-make-direct %t
+// RUN: %check_clang_tidy -std=c++17 %s modernize-make-direct %t
 
 namespace std {
 template<typename T>
@@ -40,6 +40,16 @@ template<typename T, typename U>
 pair<T,U> make_pair(T&& t, U&& u) { 
  return pair<T,U>(t, u); 
 }
+
+template<typename... T>
+struct tuple {
+ tuple(const T&... args) {}
+};
+
+template<typename... T>
+tuple<T...> make_tuple(T&&... t) {
+ return tuple<T...>(t...);
+}
 }
 
 struct Widget {
@@ -48,19 +58,19 @@ struct Widget {
 
 
 void basic_tests() {
- auto o1 = std::make_optional<int>(42);
- // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of make_optional [modernize-make-direct]
- // CHECK-FIXES: auto o1 = std::optional(42);
+  auto o1 = std::make_optional<int>(42);
+  // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of std::make_optional [modernize-make-direct]
+  // CHECK-FIXES: auto o1 = std::optional(42);
 
+  // make_unique and make_shared are not transformed by this check
   auto u1 = std::make_unique<Widget>(1);
- // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of make_unique [modernize-make-direct]
- // CHECK-FIXES: auto u1 = std::unique_ptr(new Widget(1));
-
- auto s1 = std::make_shared<Widget>(2);
-  // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of make_shared
-  // CHECK-FIXES: auto s1 = std::shared_ptr(new Widget(2));
+  auto s1 = std::make_shared<Widget>(2);
 
   auto p1 = std::make_pair(1, "test");
-  // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of make_pair
+  // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of std::make_pair [modernize-make-direct]
   // CHECK-FIXES: auto p1 = std::pair(1, "test");
+
+  auto t1 = std::make_tuple(1, 2.0, "hi");
+  // CHECK-MESSAGES: warning: use class template argument deduction (CTAD) 
instead of std::make_tuple [modernize-make-direct]
+  // CHECK-FIXES: auto t1 = std::tuple(1, 2.0, "hi");
 }

>From 837b5973366f69746a987dfd80dc4de6a7886377 Mon Sep 17 00:00:00 2001
From: Helmut Januschka <hel...@januschka.com>
Date: Tue, 10 Jun 2025 23:29:49 +0200
Subject: [PATCH 3/3] Fix CI failures: clang-format and RST title underline

- Apply clang-format fixes to MakeFunctionToDirectCheck.cpp
- Fix RST title underline length in modernize-make-direct.rst documentation
- All tests passing after fixes
---
 .../modernize/MakeFunctionToDirectCheck.cpp   | 19 +++++++++++--------
 .../modernize/modernize-make-direct.rst       |  2 +-
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git 
a/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
index 395a9a500edd1..f9eabbaefb46f 100644
--- a/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
@@ -20,22 +20,24 @@ namespace clang::tidy::modernize {
 
 namespace {
 
-RewriteRuleWith<std::string> makeFunctionToDirectCheckImpl(
-    bool CheckMakePair, bool CheckMakeOptional, bool CheckMakeTuple) {
+RewriteRuleWith<std::string>
+makeFunctionToDirectCheckImpl(bool CheckMakePair, bool CheckMakeOptional,
+                              bool CheckMakeTuple) {
   std::vector<RewriteRuleWith<std::string>> Rules;
 
   // Helper to create a rule for a specific make_* function
   auto createRule = [](StringRef MakeFunction, StringRef DirectType) {
     auto WarningMessage = cat("use class template argument deduction (CTAD) "
-                              "instead of ", MakeFunction);
+                              "instead of ",
+                              MakeFunction);
 
     return makeRule(
         callExpr(callee(functionDecl(hasName(MakeFunction))),
-                 unless(hasParent(implicitCastExpr(
-                     hasImplicitDestinationType(qualType(hasCanonicalType(
-                         qualType(asString("void")))))))))
+                 unless(hasParent(implicitCastExpr(hasImplicitDestinationType(
+                     
qualType(hasCanonicalType(qualType(asString("void")))))))))
             .bind("make_call"),
-        changeTo(node("make_call"), cat(DirectType, "(", 
callArgs("make_call"), ")")),
+        changeTo(node("make_call"),
+                 cat(DirectType, "(", callArgs("make_call"), ")")),
         WarningMessage);
   };
 
@@ -62,7 +64,8 @@ 
MakeFunctionToDirectCheck::MakeFunctionToDirectCheck(StringRef Name,
       CheckMakePair(Options.get("CheckMakePair", true)),
       CheckMakeOptional(Options.get("CheckMakeOptional", true)),
       CheckMakeTuple(Options.get("CheckMakeTuple", true)) {
-  setRule(makeFunctionToDirectCheckImpl(CheckMakePair, CheckMakeOptional, 
CheckMakeTuple));
+  setRule(makeFunctionToDirectCheckImpl(CheckMakePair, CheckMakeOptional,
+                                        CheckMakeTuple));
 }
 
 void MakeFunctionToDirectCheck::storeOptions(
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
index c11a9b66bdb22..b856c150f28cf 100644
--- 
a/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/modernize-make-direct.rst
@@ -1,7 +1,7 @@
 .. title:: clang-tidy - modernize-make-direct
 
 modernize-make-direct
-====================
+=====================
 
 Replaces ``std::make_*`` function calls with direct constructor calls using 
class template
 argument deduction (CTAD).

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

Reply via email to