Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -16,6 +16,7 @@ NonConstParameterCheck.cpp ReadabilityTidyModule.cpp RedundantControlFlowCheck.cpp + RedundantMemberInitCheck.cpp RedundantStringCStrCheck.cpp RedundantSmartptrGetCheck.cpp RedundantStringInitCheck.cpp Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -23,6 +23,7 @@ #include "NamedParameterCheck.h" #include "NonConstParameterCheck.h" #include "RedundantControlFlowCheck.h" +#include "RedundantMemberInitCheck.h" #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" #include "RedundantStringInitCheck.h" @@ -57,6 +58,8 @@ "readability-inconsistent-declaration-parameter-name"); CheckFactories.registerCheck( "readability-misplaced-array-index"); + CheckFactories.registerCheck( + "readability-redundant-member-init"); CheckFactories.registerCheck( "readability-static-definition-in-anonymous-namespace"); CheckFactories.registerCheck( Index: clang-tidy/readability/RedundantMemberInitCheck.h =================================================================== --- /dev/null +++ clang-tidy/readability/RedundantMemberInitCheck.h @@ -0,0 +1,36 @@ +//===--- RedundantMemberInitCheck.h - clang-tidy----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace readability { + +/// Finds member initializations that are unnecessary because the same default +/// constructor would be called if they were not present. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/readability-redundant-member-init.html +class RedundantMemberInitCheck : public ClangTidyCheck { +public: + RedundantMemberInitCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace readability +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_REDUNDANT_MEMBER_INIT_H Index: clang-tidy/readability/RedundantMemberInitCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/readability/RedundantMemberInitCheck.cpp @@ -0,0 +1,49 @@ +//===--- RedundantMemberInitCheck.cpp - clang-tidy-------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "RedundantMemberInitCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" +#include + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace readability { + +void RedundantMemberInitCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + cxxConstructorDecl( + ofClass(unless( + anyOf(isUnion(), ast_matchers::isTemplateInstantiation()))), + forEachConstructorInitializer( + cxxCtorInitializer( + isWritten(), + withInitializer(cxxConstructExpr().bind("construct"))) + .bind("init"))), + this); +} + +void RedundantMemberInitCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Init = Result.Nodes.getNodeAs("init"); + const auto *Construct = Result.Nodes.getNodeAs("construct"); + + if (Construct->getNumArgs() == 0 || + Construct->getArg(0)->isDefaultArgument()) { + diag(Init->getSourceLocation(), "initializer for %0 is redundant") + << Init->getMember() + << FixItHint::CreateRemoval(Init->getSourceRange()); + } +} + +} // namespace readability +} // namespace tidy +} // namespace clang Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -111,6 +111,12 @@ Flags function parameters of a pointer type that could be changed to point to a constant type instead. +- New `readability-redundant-member-init + `_ check + + Flags member initializations that are unnecessary because the same default + constructor would be called if they were not present. + Fixed bugs: - `modernize-make-unique Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -133,6 +133,7 @@ readability-named-parameter readability-non-const-parameter readability-redundant-control-flow + readability-redundant-member-init readability-redundant-smartptr-get readability-redundant-string-cstr readability-redundant-string-init Index: docs/clang-tidy/checks/readability-redundant-member-init.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/readability-redundant-member-init.rst @@ -0,0 +1,20 @@ +.. title:: clang-tidy - readability-redundant-member-init + +readability-redundant-member-init +================================= + +Finds member initializations that are unnecessary because the same default +constructor would be called if they were not present. + +Example: + +.. code-block:: c++ + + // Explicitly initializing the member s is unnecessary. + class Foo { + public: + Foo() : s() {} + + private: + std::string s; + }; Index: test/clang-tidy/readability-redundant-member-init.cpp =================================================================== --- /dev/null +++ test/clang-tidy/readability-redundant-member-init.cpp @@ -0,0 +1,113 @@ +// RUN: %check_clang_tidy %s readability-redundant-member-init %t + +struct S { + S() = default; + S(int i) : i(i) {} + int i = 1; +}; + +struct T { + T(int i = 1) : i(i) {} + int i; +}; + +struct U { + int i; +}; + +// Initializer calls default constructor +struct F1 { + F1() : f() {} + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for 'f' is redundant [readability-redundant-member-init] + // CHECK-FIXES: F1() {} + S f; +}; + +// Initializer calls default constructor with default argument +struct F2 { + F2() : f() {} + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for 'f' is redundant [readability-redundant-member-init] + // CHECK-FIXES: F2() {} + T f; +}; + +// Multiple redundant initializers for same constructor +struct F3 { + F3() : f(), g(1), h() {} + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for 'f' is redundant [readability-redundant-member-init] + // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: initializer for 'h' is redundant [readability-redundant-member-init] + // CHECK-FIXES: F3() : g(1) {} + S f, g, h; +}; + +// Templated class +template +struct F4 { + F4() : f(), g() {} + // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: initializer for 'f' is redundant [readability-redundant-member-init] + // CHECK-FIXES: F4() : g() {} + S f; + V g; +}; +F4 f4i; +F4 f4s; + +// Initializer not written +struct NF1 { + NF1() {} + S f; +}; + +// Initializer doesn't call default constructor +struct NF2 { + NF2() : f(1) {} + S f; +}; + +// Initializer calls default constructor without using default argument +struct NF3 { + NF3() : f(1) {} + T f; +}; + +// Initializer calls default constructor without using default argument +struct NF4 { + NF4() : f(2) {} + T f; +}; + +// Initializer is zero-initialization +struct NF5 { + NF5() : i() {} + int i; +}; + +// Initializer is direct-initialization +struct NF6 { + NF6() : i(1) {} + int i; +}; + +// Initializer is aggregate initialization of struct +struct NF7 { + NF7() : f{} {} + U f; +}; + +// Initializer is aggregate initialization of array +struct NF8 { + NF8() : f{} {} + int f[2]; +}; + +struct NF9 { + NF9() : f{} {} + S f[2]; +}; + +// Initializing member of union +union NF10 { + NF10() : s() {} + int i; + S s; +};