https://github.com/AntonyCJ30 updated 
https://github.com/llvm/llvm-project/pull/203474

>From 28bab72fd56f3aac2494a4b9977fda2649e63d15 Mon Sep 17 00:00:00 2001
From: AntonyCJ30 <cj6186609@[email protected]>
Date: Fri, 29 May 2026 11:15:32 +0530
Subject: [PATCH] [clang-tidy] Add modernize-default-arg-braced-init check

---
 .../clang-tidy/modernize/CMakeLists.txt       |   1 +
 .../modernize/DefaultArgBracedInitCheck.cpp   |  59 +++++++++
 .../modernize/DefaultArgBracedInitCheck.h     |  40 +++++++
 .../modernize/ModernizeTidyModule.cpp         |   3 +
 clang-tools-extra/docs/ReleaseNotes.rst       |   6 +
 .../docs/clang-tidy/checks/list.rst           |   1 +
 .../modernize/default-arg-braced-init.rst     |  20 ++++
 .../modernize/default-arg-braced-init.cpp     | 113 ++++++++++++++++++
 8 files changed, 243 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/DefaultArgBracedInitCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/DefaultArgBracedInitCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/modernize/default-arg-braced-init.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/modernize/default-arg-braced-init.cpp

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 2c5c44db587fe..4f27cfd776594 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_library(clangTidyModernizeModule STATIC
   AvoidSetjmpLongjmpCheck.cpp
   AvoidVariadicFunctionsCheck.cpp
   ConcatNestedNamespacesCheck.cpp
+  DefaultArgBracedInitCheck.cpp
   DeprecatedHeadersCheck.cpp
   DeprecatedIosBaseAliasesCheck.cpp
   IntegralLiteralExpressionMatcher.cpp
diff --git 
a/clang-tools-extra/clang-tidy/modernize/DefaultArgBracedInitCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/DefaultArgBracedInitCheck.cpp
new file mode 100644
index 0000000000000..dcd6961e9a552
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/DefaultArgBracedInitCheck.cpp
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "DefaultArgBracedInitCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+void DefaultArgBracedInitCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      parmVarDecl(hasInitializer(cxxTemporaryObjectExpr(
+                                     argumentCountIs(0),
+                                     unless(hasDeclaration(
+                                         cxxConstructorDecl(isExplicit()))))
+                                     .bind("ctor")))
+          .bind("param"),
+      this);
+}
+
+void DefaultArgBracedInitCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Ctor = Result.Nodes.getNodeAs<CXXTemporaryObjectExpr>("ctor");
+  const auto *Param = Result.Nodes.getNodeAs<ParmVarDecl>("param");
+
+  if (!Ctor || !Param)
+    return;
+
+  // Skip if inside a macro
+  const SourceLocation Loc = Ctor->getExprLoc();
+  if (Loc.isMacroID())
+    return;
+
+  // Type safety check
+  const QualType ParamType = Param->getType()
+                                 .getCanonicalType()
+                                 .getNonReferenceType()
+                                 .getUnqualifiedType();
+
+  const QualType CtorType = Ctor->getType()
+                                .getCanonicalType()
+                                .getNonReferenceType()
+                                .getUnqualifiedType();
+
+  if (ParamType != CtorType)
+    return;
+
+  auto Diag = diag(Loc, "use braced initializer list for default argument");
+  const CharSourceRange Range =
+      CharSourceRange::getTokenRange(Ctor->getBeginLoc(), Ctor->getEndLoc());
+  Diag << FixItHint::CreateReplacement(Range, "{}");
+}
+
+} // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/modernize/DefaultArgBracedInitCheck.h 
b/clang-tools-extra/clang-tidy/modernize/DefaultArgBracedInitCheck.h
new file mode 100644
index 0000000000000..bfac53a6a5573
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/DefaultArgBracedInitCheck.h
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_DEFAULTARGBRACEDINITCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_DEFAULTARGBRACEDINITCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang::tidy::modernize {
+
+/// Replaces redundant constructor calls in default arguments with braced
+/// initializer lists. For example, ``void bar(Box b = Box()) {}`` becomes
+/// ``void bar(Box b = {}) {}``.
+///
+/// For the user-facing documentation see:
+/// 
https://clang.llvm.org/extra/clang-tidy/checks/modernize/default-arg-braced-init.html
+class DefaultArgBracedInitCheck : public ClangTidyCheck {
+public:
+  DefaultArgBracedInitCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+
+  std::optional<TraversalKind> getCheckTraversalKind() const override {
+    return TK_IgnoreUnlessSpelledInSource;
+  }
+
+  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.CPlusPlus11;
+  }
+};
+
+} // namespace clang::tidy::modernize
+
+#endif // 
LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_DEFAULTARGBRACEDINITCHECK_H
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp 
b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index cc13da7535bcb..c5dea91e88025 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -14,6 +14,7 @@
 #include "AvoidSetjmpLongjmpCheck.h"
 #include "AvoidVariadicFunctionsCheck.h"
 #include "ConcatNestedNamespacesCheck.h"
+#include "DefaultArgBracedInitCheck.h"
 #include "DeprecatedHeadersCheck.h"
 #include "DeprecatedIosBaseAliasesCheck.h"
 #include "LoopConvertCheck.h"
@@ -77,6 +78,8 @@ class ModernizeModule : public ClangTidyModule {
         "modernize-avoid-variadic-functions");
     CheckFactories.registerCheck<ConcatNestedNamespacesCheck>(
         "modernize-concat-nested-namespaces");
+    CheckFactories.registerCheck<DefaultArgBracedInitCheck>(
+        "modernize-default-arg-braced-init");
     CheckFactories.registerCheck<DeprecatedHeadersCheck>(
         "modernize-deprecated-headers");
     CheckFactories.registerCheck<DeprecatedIosBaseAliasesCheck>(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index d167f5e90f88a..80130a1ed7fbf 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -263,6 +263,12 @@ New checks
 
   Finds cyclical initialization of static variables.
 
+- New :doc:`modernize-default-arg-braced-init
+  <clang-tidy/checks/modernize/default-arg-braced-init>` check.
+
+  Replaces redundant non-explicit default constructor calls in default 
arguments with braced
+  initializer lists.
+
 - New :doc:`modernize-use-std-bit
   <clang-tidy/checks/modernize/use-std-bit>` check.
 
diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst 
b/clang-tools-extra/docs/clang-tidy/checks/list.rst
index 0eb9e8a243081..98247f2a93886 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -295,6 +295,7 @@ Clang-Tidy Checks
    :doc:`modernize-avoid-setjmp-longjmp <modernize/avoid-setjmp-longjmp>`,
    :doc:`modernize-avoid-variadic-functions 
<modernize/avoid-variadic-functions>`,
    :doc:`modernize-concat-nested-namespaces 
<modernize/concat-nested-namespaces>`, "Yes"
+   :doc:`modernize-default-arg-braced-init 
<modernize/default-arg-braced-init>`, "Yes"
    :doc:`modernize-deprecated-headers <modernize/deprecated-headers>`, "Yes"
    :doc:`modernize-deprecated-ios-base-aliases 
<modernize/deprecated-ios-base-aliases>`, "Yes"
    :doc:`modernize-loop-convert <modernize/loop-convert>`, "Yes"
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/modernize/default-arg-braced-init.rst
 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/default-arg-braced-init.rst
new file mode 100644
index 0000000000000..a088c5200fa73
--- /dev/null
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/modernize/default-arg-braced-init.rst
@@ -0,0 +1,20 @@
+.. title:: clang-tidy - modernize-default-arg-braced-init
+
+modernize-default-arg-braced-init
+=================================
+
+Replaces redundant non-explicit default constructor calls in default arguments 
with a braced
+initializer list. This avoids unnecessarily repeating the type name in the
+function declaration.
+
+.. code:: c++
+
+   void func(std::string s = std::string());
+   void handle(Widget w = Widget());
+   void process(Box b = Box());
+
+   // transforms to:
+
+   void func(std::string s = {});
+   void handle(Widget w = {});
+   void process(Box b = {});
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/default-arg-braced-init.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/default-arg-braced-init.cpp
new file mode 100644
index 0000000000000..dbe328c2c258c
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/default-arg-braced-init.cpp
@@ -0,0 +1,113 @@
+// RUN: %check_clang_tidy -std=c++11-or-later %s 
modernize-default-arg-braced-init %t
+
+struct Box {
+  Box() = default;
+  Box(int x) {}
+  Box(const Box&) {}
+};
+
+struct ExplicitBox {
+  explicit ExplicitBox() {}
+};
+
+struct Base {
+  Base() = default;
+};
+
+struct Derived : Base {
+  Derived() = default;
+};
+
+
+
+// Helper function for testing nested calls
+Box makeBox(Box b) { return b; }
+
+// ========== CASES THAT SHOULD TRANSFORM ==========
+
+// Case 1: Basic transformation
+// CHECK-MESSAGES: :[[@LINE+2]]:25: warning: use braced initializer list for 
default argument
+// CHECK-FIXES: void basic_case(Box b = {}) {
+void basic_case(Box b = Box()) {
+}
+
+// Case 2: Multiple Box parameters
+// CHECK-MESSAGES: :[[@LINE+3]]:36: warning: use braced initializer list for 
default argument
+// CHECK-MESSAGES: :[[@LINE+2]]:52: warning: use braced initializer list for 
default argument
+// CHECK-FIXES: void multiple_params_case(Box b1 = {}, Box b2 = {}) {
+void multiple_params_case(Box b1 = Box(), Box b2 = Box()) {
+}
+
+// Case 3: Mixed parameter types (int, Box, double)
+// CHECK-MESSAGES: :[[@LINE+2]]:44: warning: use braced initializer list for 
default argument
+// CHECK-FIXES: void mixed_params_case(int x = 10, Box b = {}, double d = 
3.14) {
+void mixed_params_case(int x = 10, Box b = Box(), double d = 3.14) {
+}
+
+
+
+// Case 4: Template with concrete type (Box) - SHOULD transform
+// CHECK-MESSAGES: :[[@LINE+3]]:37: warning: use braced initializer list for 
default argument
+// CHECK-FIXES: void template_concrete_case(Box b = {}) {
+template<typename T>
+void template_concrete_case(Box b = Box()) {
+}
+
+// Case 5: const, const&, && parameters (all should transform)
+// CHECK-MESSAGES: :[[@LINE+4]]:38: warning: use braced initializer list for 
default argument
+// CHECK-MESSAGES: :[[@LINE+3]]:61: warning: use braced initializer list for 
default argument
+// CHECK-MESSAGES: :[[@LINE+2]]:79: warning: use braced initializer list for 
default argument
+// CHECK-FIXES: void const_ref_params(const Box b1 = {}, const Box& b2 = {}, 
Box&& b3 = {}) {
+void const_ref_params(const Box b1 = Box(), const Box& b2 = Box(), Box&& b3 = 
Box()) {
+}
+
+// Case 6: Constructor default argument (should transform)
+struct S {
+  // CHECK-MESSAGES: :[[@LINE+2]]:13: warning: use braced initializer list for 
default argument
+  // CHECK-FIXES: S(Box b = {}) {}
+  S(Box b = Box()) {}
+};
+
+// Case 7: Typedef alias (should transform)
+using MyBox = Box;
+// CHECK-MESSAGES: :[[@LINE+2]]:29: warning: use braced initializer list for 
default argument
+// CHECK-FIXES: void typedef_case(MyBox b = {}) {
+void typedef_case(MyBox b = Box()) {
+}
+
+// ========== CASES THAT SHOULD NOT TRANSFORM (SKIP) ==========
+
+// Case 8: Explicit constructor (skip)
+void explicit_case(ExplicitBox e = ExplicitBox()) {
+}
+
+// Case 9: Constructor with arguments (skip)
+void with_args_case(Box b = Box(5)) {
+}
+
+// Case 10: Type mismatch (skip)
+void type_mismatch_case(Base b = Derived()) {
+}
+
+// Case 11: Already braced (skip)
+void already_braced_case(Box b = {}) {
+}
+
+// Case 12: Template with dependent type T() - SHOULD NOT transform
+template<typename T>
+void template_dependent_case(T t = T()) {
+}
+
+// Case 13: Macro expansion (skip)
+#define DEFAULT_BOX Box()
+void macro_case(Box b = DEFAULT_BOX) {
+}
+#undef DEFAULT_BOX
+
+// Case 14: Ternary operator with Box() (skip - nested)
+void ternary_case(Box b = true ? Box() : Box()) {
+}
+
+// Case 15: Nested function call (skip - nested)
+void nested_call_case(Box b = makeBox(Box())) {
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to