Author: serge-sans-paille
Date: 2026-10-10T07:12:06Z
New Revision: e3f3b3e565d9fe9d5c261487eb8df68b19acffa8

URL: 
https://github.com/llvm/llvm-project/commit/e3f3b3e565d9fe9d5c261487eb8df68b19acffa8
DIFF: 
https://github.com/llvm/llvm-project/commit/e3f3b3e565d9fe9d5c261487eb8df68b19acffa8.diff

LOG: [clang-tidy] Improve modernize-use-equals-default check to handle explicit 
parent constructor calls (#226456)

Now capture this pattern:

struct Base {};
struct C : Base {
    C() : Base() {}
};

And turn it into

struct Base {};
struct C : Base {
    C() = default;
};

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
    clang-tools-extra/docs/ReleaseNotes.md
    clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
index 1535fa79676abf..af8774dc09f359 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseEqualsDefaultCheck.cpp
@@ -247,7 +247,9 @@ void UseEqualsDefaultCheck::registerMatchers(MatchFinder 
*Finder) {
           anyOf(
               // Default constructor.
               allOf(parameterCountIs(0),
-                    unless(hasAnyConstructorInitializer(isWritten())),
+                    unless(hasAnyConstructorInitializer(allOf(
+                        isWritten(), unless(withInitializer(cxxConstructExpr(
+                                         argumentCountIs(0))))))),
                     unless(isVariadic()), IsPublicOrOutOfLineUntilCPP20),
               // Copy constructor.
               allOf(isCopyConstructor(),
@@ -319,11 +321,13 @@ void UseEqualsDefaultCheck::check(const 
MatchFinder::MatchResult &Result) {
       if (!isCopyConstructorAndCanBeDefaulted(Result.Context, Ctor))
         return;
       MemberType = 1;
-      // If there are constructor initializers, they must be removed.
-      for (const auto *Init : Ctor->inits()) {
-        RemoveInitializers.emplace_back(
-            FixItHint::CreateRemoval(Init->getSourceRange()));
-      }
+    }
+    // If there are constructor initializers, they must be removed.
+    for (const auto *Init : Ctor->inits()) {
+      if (!Init->isWritten())
+        continue;
+      RemoveInitializers.emplace_back(
+          FixItHint::CreateRemoval(Init->getSourceRange()));
     }
   } else if (isa<CXXDestructorDecl>(SpecialFunctionDecl)) {
     MemberType = 2;

diff  --git a/clang-tools-extra/docs/ReleaseNotes.md 
b/clang-tools-extra/docs/ReleaseNotes.md
index ce498ff6a4388b..25bc3ba0ed73fe 100644
--- a/clang-tools-extra/docs/ReleaseNotes.md
+++ b/clang-tools-extra/docs/ReleaseNotes.md
@@ -273,6 +273,10 @@ infrastructure are described first, followed by 
tool-specific sections.
   <clang-tidy/checks/modernize/use-designated-initializers>` when analyzing
   malformed code with nested classes and ambiguous initializer.
 
+- Improved {doc}`modernize-use-equals-default
+  <clang-tidy/checks/modernize/use-equals-default>` check to also capture
+  default constructor with explicit default-initialization of parents.
+
 - Fixed a crash in {doc}`modernize-use-noexcept
   <clang-tidy/checks/modernize/use-noexcept>` when analyzing malformed template
   code with an unparsed exception specification.

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default.cpp
index 2eefdf9d6460ca..00264c7d51f5c8 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-equals-default.cpp
@@ -236,11 +236,39 @@ ODef::~ODef() = default;
 // Delegating constructor and overriden destructor.
 struct DC : KW {
   DC() : KW() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: DC() = default;
   ~DC() override {}
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
   // CHECK-FIXES: ~DC() override = default;
 };
 
+// Delegating constructor with multiple initializers.
+struct DCM : KW, N {
+  DCM() : KW(), N() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: DCM() = default;
+};
+
+struct dummy {};
+
+// Delegating constructor with field initializer.
+struct DCF : KW {
+
+  DCF() : KW(), d() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: DCF() = default;
+
+  dummy d;
+};
+
+// Delegating constructor with noexcept.
+struct DCNE : KW {
+  DCNE() noexcept : KW() {}
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'
+  // CHECK-FIXES: DCNE() noexcept = default;
+};
+
 struct OverrideWithSemiColon : KW {
   ~OverrideWithSemiColon() override {};
   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default'


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

Reply via email to