summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Smolsky <oleg.smolsky@gmail.com>2022-01-04 07:27:02 -0500
committerAaron Ballman <aaron@aaronballman.com>2022-01-04 07:27:02 -0500
commit051847cfecaea3f55fc4f822facfbf5d21bde8dd (patch)
treef33554dca908481af9835cb3560de698b4f3e36f
parent95b74d4db0686a8d55fdae1af4e985ea52b2c572 (diff)
downloadllvm-051847cfecaea3f55fc4f822facfbf5d21bde8dd.tar.gz
Improve the 'modernize-use-default-member-init'
We want to deal with non-default constructors that just happen to contain constant initializers. There was already a negative test case, it is now a positive one. We find and refactor this case: struct PositiveNotDefaultInt { PositiveNotDefaultInt(int) : i(7) {} int i; };
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp27
-rw-r--r--clang-tools-extra/docs/ReleaseNotes.rst3
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/modernize-use-default-member-init.rst2
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/modernize-use-default-member-init.cpp42
4 files changed, 56 insertions, 18 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
index 6e7e37236b19..d57a88d66883 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
@@ -212,17 +212,14 @@ void UseDefaultMemberInitCheck::registerMatchers(MatchFinder *Finder) {
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 @@ void UseDefaultMemberInitCheck::checkDefaultInit(
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<CXXRecordDecl>(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
index 6f8a25e0d04f..5d330d1d2e3c 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -73,6 +73,9 @@ Improvements to clang-tidy
- 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
index a77415301ef6..2d3ed3801493 100644
--- 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
index 27c947820d9c..464cfbdeacb8 100644
--- 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 @@ struct PositiveInt {
// 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 @@ struct NegativeBitField
int i : 5;
};
-struct NegativeNotDefaultInt
-{
- NegativeNotDefaultInt(int) : i(7) {}
- int i;
-};
-
struct NegativeDefaultArg
{
NegativeDefaultArg(int i = 4) : i(i) {}