summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp22
-rw-r--r--clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h8
-rw-r--r--clang-tools-extra/docs/ReleaseNotes.rst7
-rw-r--r--clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst27
-rw-r--r--clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp35
5 files changed, 91 insertions, 8 deletions
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
index d38d0a233e4..cf48bbdc621 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
@@ -20,6 +20,11 @@ namespace clang {
namespace tidy {
namespace readability {
+void RedundantMemberInitCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "IgnoreBaseInCopyConstructors",
+ IgnoreBaseInCopyConstructors);
+}
+
void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {
if (!getLangOpts().CPlusPlus)
return;
@@ -36,17 +41,24 @@ void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) {
ofClass(unless(
anyOf(isUnion(), ast_matchers::isTemplateInstantiation()))),
forEachConstructorInitializer(
- cxxCtorInitializer(isWritten(),
- withInitializer(ignoringImplicit(Construct)),
- unless(forField(hasType(isConstQualified()))),
- unless(forField(hasParent(recordDecl(isUnion())))))
- .bind("init"))),
+ cxxCtorInitializer(
+ isWritten(), withInitializer(ignoringImplicit(Construct)),
+ unless(forField(hasType(isConstQualified()))),
+ unless(forField(hasParent(recordDecl(isUnion())))))
+ .bind("init")))
+ .bind("constructor"),
this);
}
void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
const auto *Init = Result.Nodes.getNodeAs<CXXCtorInitializer>("init");
const auto *Construct = Result.Nodes.getNodeAs<CXXConstructExpr>("construct");
+ const auto *ConstructorDecl =
+ Result.Nodes.getNodeAs<CXXConstructorDecl>("constructor");
+
+ if (IgnoreBaseInCopyConstructors && ConstructorDecl->isCopyConstructor() &&
+ Init->isBaseInitializer())
+ return;
if (Construct->getNumArgs() == 0 ||
Construct->getArg(0)->isDefaultArgument()) {
diff --git a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
index 73ced118b15..b8e11a6ceee 100644
--- a/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
@@ -23,9 +23,15 @@ namespace readability {
class RedundantMemberInitCheck : public ClangTidyCheck {
public:
RedundantMemberInitCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
+ : ClangTidyCheck(Name, Context),
+ IgnoreBaseInCopyConstructors(
+ Options.get("IgnoreBaseInCopyConstructors", 0)) {}
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ bool IgnoreBaseInCopyConstructors;
};
} // namespace readability
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index b9feee29d13..bee80210527 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -176,6 +176,13 @@ Improvements to clang-tidy
The check now supports the ``AllowOverrideAndFinal`` option to eliminate
conflicts with ``gcc -Wsuggest-override`` or ``gcc -Werror=suggest-override``.
+- Improved :doc:`readability-redundant-member-init
+ <clang-tidy/checks/readability-redundant-member-init>` check.
+
+ The check now supports the ``IgnoreBaseInCopyConstructors`` option to avoid
+ `"base class \‘Foo\’ should be explicitly initialized in the copy constructor"`
+ warnings or errors with ``gcc -Wextra`` or ``gcc -Werror=extra``.
+
- The :doc:`readability-redundant-string-init
<clang-tidy/checks/readability-redundant-string-init>` check now supports a
`StringNames` option enabling its application to custom string classes.
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
index a640e16e3c0..116de1f3dd3 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
@@ -6,7 +6,8 @@ readability-redundant-member-init
Finds member initializations that are unnecessary because the same default
constructor would be called if they were not present.
-Example:
+Example
+-------
.. code-block:: c++
@@ -18,3 +19,27 @@ Example:
private:
std::string s;
};
+
+Options
+-------
+
+.. option:: IgnoreBaseInCopyConstructors
+
+ Default is ``0``.
+
+ When non-zero, the check will ignore unnecessary base class initializations
+ within copy constructors, since some compilers issue warnings/errors when
+ base classes are not explicitly intialized in copy constructors. For example,
+ ``gcc`` with ``-Wextra`` or ``-Werror=extra`` issues warning or error
+ ``base class ‘Bar’ should be explicitly initialized in the copy constructor``
+ if ``Bar()`` were removed in the following example:
+
+.. code-block:: c++
+
+ // Explicitly initializing member s and base class Bar is unnecessary.
+ struct Foo : public Bar {
+ // Remove s() below. If IgnoreBaseInCopyConstructors!=0, keep Bar().
+ Foo(const Foo& foo) : Bar(), s() {}
+ std::string s;
+ };
+
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
index 90b52fd1a48..0f8c028aabb 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
@@ -1,4 +1,8 @@
-// RUN: %check_clang_tidy %s readability-redundant-member-init %t
+// RUN: %check_clang_tidy %s readability-redundant-member-init %t \
+// RUN: -config="{CheckOptions: \
+// RUN: [{key: readability-redundant-member-init.IgnoreBaseInCopyConstructors, \
+// RUN: value: 1}] \
+// RUN: }"
struct S {
S() = default;
@@ -116,6 +120,35 @@ struct F9 {
};
};
+// struct whose inline copy constructor default-initializes its base class
+struct WithCopyConstructor1 : public T {
+ WithCopyConstructor1(const WithCopyConstructor1& other) : T(),
+ f(),
+ g()
+ {}
+ S f, g;
+};
+// No warning in copy constructor about T since IgnoreBaseInCopyConstructors=1
+// CHECK-MESSAGES: :[[@LINE-6]]:5: warning: initializer for member 'f' is redundant
+// CHECK-MESSAGES: :[[@LINE-6]]:5: warning: initializer for member 'g' is redundant
+// CHECK-FIXES: WithCopyConstructor1(const WithCopyConstructor1& other) : T()
+// CHECK-NEXT:
+// CHECK-NEXT:
+// CHECK-NEXT: {}
+
+// struct whose copy constructor default-initializes its base class
+struct WithCopyConstructor2 : public T {
+ WithCopyConstructor2(const WithCopyConstructor2& other);
+ S a;
+};
+WithCopyConstructor2::WithCopyConstructor2(const WithCopyConstructor2& other)
+ : T(), a()
+{}
+// No warning in copy constructor about T since IgnoreBaseInCopyConstructors=1
+// CHECK-MESSAGES: :[[@LINE-3]]:10: warning: initializer for member 'a' is redundant
+// CHECK-FIXES: {{^}} : T() {{$}}
+// CHECK-NEXT: {}
+
// Initializer not written
struct NF1 {
NF1() {}
OpenPOWER on IntegriCloud