llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tidy

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

Author: Helmut Januschka (hjanuschka)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/118120.diff


7 Files Affected:

- (modified) clang-tools-extra/clang-tidy/modernize/CMakeLists.txt (+1) 
- (added) clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp 
(+78) 
- (added) clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h 
(+39) 
- (modified) clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
(+3) 
- (modified) clang-tools-extra/docs/ReleaseNotes.rst (+6) 
- (added) clang-tools-extra/docs/clang-tidy/checks/modernize/make-direct.rst 
(+46) 
- (added) 
clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp 
(+76) 


``````````diff
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..f9eabbaefb46f
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.cpp
@@ -0,0 +1,78 @@
+//===--- 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 "../utils/TransformerClangTidyCheck.h"
+#include "clang/ASTMatchers/ASTMatchers.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::transformer;
+
+namespace clang::tidy::modernize {
+
+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"));
+  }
+
+  if (CheckMakePair) {
+    Rules.push_back(createRule("std::make_pair", "std::pair"));
+  }
+
+  if (CheckMakeTuple) {
+    Rules.push_back(createRule("std::make_tuple", "std::tuple"));
+  }
+
+  return applyFirst(Rules);
+}
+
+} // namespace
+
+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));
+}
+
+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
new file mode 100644
index 0000000000000..c3637b2bc00dc
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/MakeFunctionToDirectCheck.h
@@ -0,0 +1,39 @@
+//===--- 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 {
+
+/// 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);
+
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus17;
+  }
+
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+
+private:
+  const bool CheckMakePair;
+  const bool CheckMakeOptional;
+  const bool CheckMakeTuple;
+};
+
+} // 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 e872759856f3c..4c6964a729346 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..8917627b13ea0 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_pair, and make_tuple 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/make-direct.rst 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/make-direct.rst
new file mode 100644
index 0000000000000..b856c150f28cf
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/make-direct.rst
@@ -0,0 +1,46 @@
+.. 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_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
new file mode 100644
index 0000000000000..2a1fe4713ecb9
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/make-direct-check.cpp
@@ -0,0 +1,76 @@
+// RUN: %check_clang_tidy -std=c++17 %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); 
+}
+
+template<typename... T>
+struct tuple {
+ tuple(const T&... args) {}
+};
+
+template<typename... T>
+tuple<T...> make_tuple(T&&... t) {
+ return tuple<T...>(t...);
+}
+}
+
+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 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);
+  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 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");
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/118120
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to