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 @@ -1,3 +1,4 @@ + //===--- UseDefaultMemberInitCheck.cpp - clang-tidy------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. @@ -212,17 +213,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 +246,13 @@ 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. + auto ClassDecl = dyn_cast(Field->getParent()); + if (std::count_if(ClassDecl->ctors().begin(), ClassDecl->ctors().end(), + [](const auto Ctor) { return !Ctor->isCopyOrMoveConstructor(); }) > 1) + return; + SourceLocation StartLoc = Field->getBeginLoc(); if (StartLoc.isMacroID() && IgnoreMacros) return; 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) {}