poelmanc updated this revision to Diff 226847.
poelmanc added a comment.

Changed default to 1, updated help accordingly, and removed an extraneous set 
of braces around a one-line statement.


Repository:
  rCTE Clang Tools Extra

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69145/new/

https://reviews.llvm.org/D69145

Files:
  clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
  clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
  clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
  
clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/readability-redundant-member-init.cpp
+++ 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:   -config="{CheckOptions: \
+// RUN:             [{key: readability-redundant-member-init.IgnoreBaseInCopyConstructors, \
+// RUN:               value: 1}] \
+// RUN:             }"
 
 struct S {
   S() = default;
@@ -116,6 +120,35 @@
   };
 };
 
+// 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() {}
Index: clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
+++ clang-tools-extra/docs/clang-tidy/checks/readability-redundant-member-init.rst
@@ -6,7 +6,8 @@
 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 @@
   private:
     std::string s;
   };
+
+Options
+-------
+
+.. option:: IgnoreBaseInCopyConstructors
+
+    Default is ``1``.
+
+    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;
+  };
+
Index: clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
===================================================================
--- clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
+++ clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.h
@@ -23,9 +23,15 @@
 class RedundantMemberInitCheck : public ClangTidyCheck {
 public:
   RedundantMemberInitCheck(StringRef Name, ClangTidyContext *Context)
-      : ClangTidyCheck(Name, Context) {}
+      : ClangTidyCheck(Name, Context),
+        IgnoreBaseInCopyConstructors(
+            Options.get("IgnoreBaseInCopyConstructors", 1)) {}
+  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
Index: clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
+++ clang-tools-extra/clang-tidy/readability/RedundantMemberInitCheck.cpp
@@ -20,6 +20,11 @@
 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 @@
           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()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to