diff --git a/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp --- a/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp @@ -212,17 +212,14 @@ InitBase); Finder->addMatcher( - cxxConstructorDecl( - isDefaultConstructor(), - forEachConstructorInitializer( - cxxCtorInitializer( - forField(unless(anyOf(getLangOpts().CPlusPlus20 - ? unless(anything()) - : isBitField(), - hasInClassInitializer(anything()), - hasParent(recordDecl(isUnion()))))), - withInitializer(Init)) - .bind("default"))), + cxxConstructorDecl(forEachConstructorInitializer( + cxxCtorInitializer( + forField(unless(anyOf( + getLangOpts().CPlusPlus20 ? unless(anything()) : isBitField(), + hasInClassInitializer(anything()), + hasParent(recordDecl(isUnion()))))), + withInitializer(Init)) + .bind("default"))), this); Finder->addMatcher( @@ -248,6 +245,14 @@ const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) { const FieldDecl *Field = Init->getAnyMember(); + // Check whether we have multiple hand-written constructors and bomb out, as + // it is hard to reconcile their sets of member initializers. + const auto *ClassDecl = dyn_cast(Field->getParent()); + if (llvm::count_if(ClassDecl->ctors(), [](const CXXConstructorDecl *Ctor) { + return !Ctor->isCopyOrMoveConstructor(); + }) > 1) + return; + SourceLocation StartLoc = Field->getBeginLoc(); if (StartLoc.isMacroID() && IgnoreMacros) return; diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -73,6 +73,9 @@ - Added support for `NOLINTBEGIN` ... `NOLINTEND` comments to suppress Clang-Tidy warnings over multiple lines. +- Generalized the `modernize-use-default-member-init` check to handle non-default + constructors. + New checks ^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst --- a/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst @@ -3,7 +3,7 @@ modernize-use-default-member-init ================================= -This check converts a default constructor's member initializers into the new +This check converts constructors' member initializers into the new default member initializers in C++11. Other member initializers that match the default member initializer are removed. This can reduce repeated code or allow use of '= default'. diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp @@ -45,6 +45,42 @@ // CHECK-FIXES: int j{1}; }; +struct PositiveNotDefaultInt { + PositiveNotDefaultInt(int) : i(7) {} + // CHECK-FIXES: PositiveNotDefaultInt(int) {} + int i; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'i' + // CHECK-FIXES: int i{7}; +}; + +// We cannot reconcile these initializers. +struct TwoConstructors { + TwoConstructors(int) : i(7) {} + TwoConstructors(int, int) : i(8) {} + int i; +}; + +struct PositiveNotDefaultOOLInt { + PositiveNotDefaultOOLInt(int); + int i; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'i' + // CHECK-FIXES: int i{7}; +}; + +PositiveNotDefaultOOLInt::PositiveNotDefaultOOLInt(int) : i(7) {} +// CHECK-FIXES: PositiveNotDefaultOOLInt::PositiveNotDefaultOOLInt(int) {} + +struct PositiveNotDefaultOOLInt2 { + PositiveNotDefaultOOLInt2(int, int); + int i; + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'i' + // CHECK-FIXES: int i{7}; + int j; +}; + +PositiveNotDefaultOOLInt2::PositiveNotDefaultOOLInt2(int, int arg) : i(7), j(arg) {} +// CHECK-FIXES: PositiveNotDefaultOOLInt2::PositiveNotDefaultOOLInt2(int, int arg) : j(arg) {} + struct PositiveUnaryMinusInt { PositiveUnaryMinusInt() : j(-1) {} // CHECK-FIXES: PositiveUnaryMinusInt() {} @@ -234,12 +270,6 @@ int i : 5; }; -struct NegativeNotDefaultInt -{ - NegativeNotDefaultInt(int) : i(7) {} - int i; -}; - struct NegativeDefaultArg { NegativeDefaultArg(int i = 4) : i(i) {}