malcolm.parsons updated this revision to Diff 78363.
malcolm.parsons added a comment.
Remove doubled spaces
https://reviews.llvm.org/D26750
Files:
clang-tidy/modernize/CMakeLists.txt
clang-tidy/modernize/ModernizeTidyModule.cpp
clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
clang-tidy/modernize/UseDefaultMemberInitCheck.h
docs/ReleaseNotes.rst
docs/clang-tidy/checks/list.rst
docs/clang-tidy/checks/modernize-use-default-member-init.rst
test/clang-tidy/modernize-use-default-member-init-assignment.cpp
test/clang-tidy/modernize-use-default-member-init.cpp
Index: test/clang-tidy/modernize-use-default-member-init.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-use-default-member-init.cpp
@@ -0,0 +1,202 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- -- -std=c++11
+
+struct S {
+};
+
+struct PositiveValueInt {
+ PositiveValueInt() : i() {}
+ // CHECK-FIXES: PositiveValueInt() {}
+ const int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use default member initializer for 'i' [modernize-use-default-member-init]
+ // CHECK-FIXES: const int i{};
+};
+
+struct PositiveInt {
+ PositiveInt() : j(1) {}
+ // CHECK-FIXES: PositiveInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j' [modernize-use-default-member-init]
+ // CHECK-FIXES: int j{1};
+};
+
+struct PositiveValueDouble {
+ PositiveValueDouble() : d() {}
+ // CHECK-FIXES: PositiveValueDouble() {}
+ double d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'd' [modernize-use-default-member-init]
+ // CHECK-FIXES: double d{};
+};
+
+struct PositiveDouble {
+ PositiveDouble() : f(2.5463e43) {}
+ // CHECK-FIXES: PositiveDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f' [modernize-use-default-member-init]
+ // CHECK-FIXES: double f{2.5463e43};
+};
+
+struct PositiveValueBool {
+ PositiveValueBool() : b() {}
+ // CHECK-FIXES: PositiveValueBool() {}
+ bool b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'b' [modernize-use-default-member-init]
+ // CHECK-FIXES: bool b{};
+};
+
+struct PositiveBool {
+ PositiveBool() : a(true) {}
+ // CHECK-FIXES: PositiveBool() {}
+ bool a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'a' [modernize-use-default-member-init]
+ // CHECK-FIXES: bool a{true};
+};
+
+struct PositiveValuePointer {
+ PositiveValuePointer() : p() {}
+ // CHECK-FIXES: PositiveValuePointer() {}
+ int *p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'p' [modernize-use-default-member-init]
+ // CHECK-FIXES: int *p{};
+};
+
+struct PositiveNullPointer {
+ PositiveNullPointer() : q(nullptr) {}
+ // CHECK-FIXES: PositiveNullPointer() {}
+ int *q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'q' [modernize-use-default-member-init]
+ // CHECK-FIXES: int *q{nullptr};
+};
+
+enum Enum { Foo, Bar };
+struct PositiveEnum {
+ PositiveEnum() : e(Foo) {}
+ // CHECK-FIXES: PositiveEnum() {}
+ Enum e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e' [modernize-use-default-member-init]
+ // CHECK-FIXES: Enum e{Foo};
+};
+
+struct NegativeMemberInit {
+ NegativeMemberInit() {}
+ int i = 2;
+};
+
+struct NegativeClass : S {
+ NegativeClass() : s() {}
+ S s;
+};
+
+struct NegativeBase : S {
+ NegativeBase() : S() {}
+};
+
+struct NegativeDefaultOtherMember{
+ NegativeDefaultOtherMember() : i(3) {}
+ int i = 4;
+};
+
+struct NegativeUnion {
+ NegativeUnion() : d(5.0) {}
+ union {
+ int i;
+ double d;
+ };
+};
+
+struct NegativeBitField
+{
+ NegativeBitField() : i(6) {}
+ int i : 5;
+};
+
+struct NegativeNotDefaultInt
+{
+ NegativeNotDefaultInt(int) : i(7) {}
+ int i;
+};
+
+struct ExistingInt {
+ ExistingInt(short) : e1(), e2(), e3(), e4() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:30: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingInt(short) : e3(), e4() {}
+ ExistingInt(int) : e1(0), e2(0), e3(0), e4(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingInt(int) : e3(0), e4(0) {}
+ ExistingInt(long) : e1(5), e2(5), e3(5), e4(5) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: member initializer for 'e3' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: member initializer for 'e4' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingInt(long) : e1(5), e2(5) {}
+ int e1{};
+ int e2 = 0;
+ int e3 = {5};
+ int e4 = 5;
+};
+
+struct ExistingDouble {
+ ExistingDouble(short) : e1(), e2(), e3() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingDouble(short) : e3() {}
+ ExistingDouble(int) : e1(0.0), e2(0.0), e3(0.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingDouble(int) : e3(0.0) {}
+ ExistingDouble(long) : e1(5.0), e2(5.0), e3(5.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: member initializer for 'e3' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingDouble(long) : e1(5.0), e2(5.0) {}
+ double e1{};
+ double e2 = 0.0;
+ double e3 = 5.0;
+};
+
+struct ExistingBool {
+ ExistingBool(short) : e1(), e2(), e3() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingBool(short) : e3() {}
+ ExistingBool(int) : e1(false), e2(false), e3(false) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingBool(int) : e3(false) {}
+ ExistingBool(long) : e1(true), e2(true), e3(true) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: member initializer for 'e3' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingBool(long) : e1(true), e2(true) {}
+ bool e1{};
+ bool e2 = false;
+ bool e3 = true;
+};
+
+struct ExistingEnum {
+ ExistingEnum(short) : e1(Foo), e2(Foo) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingEnum(short) : e2(Foo) {}
+ ExistingEnum(int) : e1(Bar), e2(Bar) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingEnum(int) : e1(Bar) {}
+ Enum e1 = Foo;
+ Enum e2{Bar};
+};
+
+struct ExistingPointer {
+ ExistingPointer(short) : e1(), e2(), e3(), e4() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-3]]:40: warning: member initializer for 'e3' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingPointer(short) : e4() {}
+ ExistingPointer(int) : e1(0), e2(0), e3(0), e4(&e1) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-3]]:40: warning: member initializer for 'e3' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingPointer(int) : e4(&e1) {}
+ ExistingPointer(long) : e1(nullptr), e2(nullptr), e3(nullptr), e4(&e2) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-2]]:40: warning: member initializer for 'e2' is redundant [modernize-use-default-member-init]
+ // CHECK-MESSAGES: :[[@LINE-3]]:53: warning: member initializer for 'e3' is redundant [modernize-use-default-member-init]
+ // CHECK-FIXES: ExistingPointer(long) : e4(&e2) {}
+ int *e1{};
+ int *e2 = 0;
+ int *e3 = nullptr;
+ int **e4 = &e1;
+};
Index: test/clang-tidy/modernize-use-default-member-init-assignment.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/modernize-use-default-member-init-assignment.cpp
@@ -0,0 +1,79 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- \
+// RUN: -config="{CheckOptions: [{key: modernize-use-default-member-init.UseAssignment, value: 1}]}" -- -std=c++11
+
+struct S {
+};
+
+struct PositiveValueInt {
+ PositiveValueInt() : i() {}
+ // CHECK-FIXES: PositiveValueInt() {}
+ const int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use default member initializer for 'i' [modernize-use-default-member-init]
+ // CHECK-FIXES: const int i = 0;
+};
+
+struct PositiveInt {
+ PositiveInt() : j(1) {}
+ // CHECK-FIXES: PositiveInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j' [modernize-use-default-member-init]
+ // CHECK-FIXES: int j = 1;
+};
+
+struct PositiveValueDouble {
+ PositiveValueDouble() : d() {}
+ // CHECK-FIXES: PositiveValueDouble() {}
+ double d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'd' [modernize-use-default-member-init]
+ // CHECK-FIXES: double d = 0.0;
+};
+
+struct PositiveDouble {
+ PositiveDouble() : f(2.5463e43) {}
+ // CHECK-FIXES: PositiveDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f' [modernize-use-default-member-init]
+ // CHECK-FIXES: double f = 2.5463e43;
+};
+
+struct PositiveValueBool {
+ PositiveValueBool() : b() {}
+ // CHECK-FIXES: PositiveValueBool() {}
+ bool b;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'b' [modernize-use-default-member-init]
+ // CHECK-FIXES: bool b = false;
+};
+
+struct PositiveBool {
+ PositiveBool() : a(true) {}
+ // CHECK-FIXES: PositiveBool() {}
+ bool a;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'a' [modernize-use-default-member-init]
+ // CHECK-FIXES: bool a = true;
+};
+
+struct PositiveValuePointer {
+ PositiveValuePointer() : p() {}
+ // CHECK-FIXES: PositiveValuePointer() {}
+ int *p;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'p' [modernize-use-default-member-init]
+ // CHECK-FIXES: int *p = nullptr;
+};
+
+struct PositiveNullPointer {
+ PositiveNullPointer() : q(nullptr) {}
+ // CHECK-FIXES: PositiveNullPointer() {}
+ int *q;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'q' [modernize-use-default-member-init]
+ // CHECK-FIXES: int *q = nullptr;
+};
+
+enum Enum { Foo };
+struct PositiveEnum {
+ PositiveEnum() : e(Foo) {}
+ // CHECK-FIXES: PositiveEnum() {}
+ Enum e;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'e' [modernize-use-default-member-init]
+ // CHECK-FIXES: Enum e = Foo;
+};
+
Index: docs/clang-tidy/checks/modernize-use-default-member-init.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/modernize-use-default-member-init.rst
@@ -0,0 +1,49 @@
+.. title:: clang-tidy - modernize-use-default-member-init
+
+modernize-use-default-member-init
+=================================
+
+This check converts a default constructor's member initializers into default
+member initializers. Other member initializers that match the default
+member initializer are removed. This can reduce repeated code or allow use of
+'= default'.
+
+.. code-block:: c++
+
+ struct A {
+ A() : i(5), j(10.0) {}
+ A(int i) : i(i), j(10.0) {}
+ int i;
+ double j;
+ };
+
+ // becomes
+
+ struct A {
+ A() {}
+ A(int i) : i(i) {}
+ int i{5};
+ double j{10.0};
+ };
+
+.. note::
+ Only converts member initializers for built-in types, enums and pointers.
+ The `readability-redundant-member-init` check will remove redundant member
+ initializers for classes.
+
+Options
+-------
+
+.. option:: UseAssignment
+
+ If this option is set to non-zero (default is `0`), the check will initialise
+ members with an assignment. For example:
+
+.. code-block:: c++
+
+ struct A {
+ A() {}
+ A(int i) : i(i) {}
+ int i = 5;
+ double j = 10.0;
+ };
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -110,6 +110,7 @@
modernize-use-auto
modernize-use-bool-literals
modernize-use-default
+ modernize-use-default-member-init
modernize-use-emplace
modernize-use-equals-delete
modernize-use-nullptr
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -91,6 +91,12 @@
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-auto.html>`_ check
now warns about variable declarations that are initialized with a cast.
+- New `modernize-use-default-member-init
+ <http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-default-member-init.html>`_ check
+
+ Converts a default constructor's member initializers into default member initializers.
+ Removes member initializers that are the same as a default member initializer.
+
- New `modernize-use-equals-delete
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-equals-delete.html>`_ check
Index: clang-tidy/modernize/UseDefaultMemberInitCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/modernize/UseDefaultMemberInitCheck.h
@@ -0,0 +1,45 @@
+//===--- UseDefaultMemberInitCheck.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_MODERNIZE_USE_DEFAULT_MEMBER_INIT_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_DEFAULT_MEMBER_INIT_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Convert a default constructor's member initializers into default member
+/// initializers. Remove member initializers that are the same as a default
+/// member initializer.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-default-member-init.html
+class UseDefaultMemberInitCheck : public ClangTidyCheck {
+public:
+ UseDefaultMemberInitCheck(StringRef Name, ClangTidyContext *Context);
+ void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ void checkDefaultInit(const ast_matchers::MatchFinder::MatchResult &Result,
+ const CXXCtorInitializer *Init);
+ void checkExistingInit(const ast_matchers::MatchFinder::MatchResult &Result,
+ const CXXCtorInitializer *Init);
+
+ const bool UseAssignment;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_DEFAULT_MEMBER_INIT_H
Index: clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
@@ -0,0 +1,189 @@
+//===--- UseDefaultMemberInitCheck.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 "UseDefaultMemberInitCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+static StringRef getValueInit(const CXXCtorInitializer *Init) {
+ switch (Init->getInit()->getType()->getScalarTypeKind()) {
+ case Type::STK_CPointer:
+ case Type::STK_BlockPointer:
+ case Type::STK_ObjCObjectPointer:
+ case Type::STK_MemberPointer:
+ return "nullptr";
+ case Type::STK_Bool:
+ return "false";
+ case Type::STK_Integral:
+ return "0";
+ case Type::STK_Floating:
+ case Type::STK_IntegralComplex:
+ case Type::STK_FloatingComplex:
+ return "0.0";
+ }
+ return "";
+}
+
+static bool isZero(const Expr *E) {
+ switch (E->getStmtClass()) {
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::ImplicitValueInitExprClass:
+ return true;
+ case Stmt::InitListExprClass:
+ return cast<InitListExpr>(E)->getNumInits() == 0;
+ case Stmt::CXXBoolLiteralExprClass:
+ return !cast<CXXBoolLiteralExpr>(E)->getValue();
+ case Stmt::IntegerLiteralClass:
+ return !cast<IntegerLiteral>(E)->getValue();
+ case Stmt::FloatingLiteralClass: {
+ llvm::APFloat Value = cast<FloatingLiteral>(E)->getValue();
+ return Value.isZero() && !Value.isNegative();
+ }
+ default:
+ return false;
+ }
+}
+
+static const Expr *getInitializer(const Expr *E) {
+ auto *InitList = dyn_cast<InitListExpr>(E);
+ if (InitList && InitList->getNumInits() == 1) {
+ return InitList->getInit(0);
+ }
+ return E;
+}
+
+static bool sameValue(const Expr *E1, const Expr *E2) {
+ E1 = getInitializer(E1->IgnoreImpCasts());
+ E2 = getInitializer(E2->IgnoreImpCasts());
+
+ if (isZero(E1) && isZero(E2)) {
+ return true;
+ }
+
+ if (E1->getStmtClass() != E2->getStmtClass()) {
+ return false;
+ }
+
+ switch (E1->getStmtClass()) {
+ case Stmt::CXXBoolLiteralExprClass:
+ return cast<CXXBoolLiteralExpr>(E1)->getValue() ==
+ cast<CXXBoolLiteralExpr>(E2)->getValue();
+ case Stmt::IntegerLiteralClass:
+ return cast<IntegerLiteral>(E1)->getValue() ==
+ cast<IntegerLiteral>(E2)->getValue();
+ case Stmt::FloatingLiteralClass:
+ return cast<FloatingLiteral>(E1)->getValue().bitwiseIsEqual(
+ cast<FloatingLiteral>(E2)->getValue());
+ case Stmt::DeclRefExprClass:
+ return cast<DeclRefExpr>(E1)->getDecl() == cast<DeclRefExpr>(E2)->getDecl();
+ default:
+ break;
+ }
+ return false;
+}
+
+UseDefaultMemberInitCheck::UseDefaultMemberInitCheck(StringRef Name,
+ ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context),
+ UseAssignment(Options.get("UseAssignment", 0) != 0) {}
+
+void UseDefaultMemberInitCheck::storeOptions(
+ ClangTidyOptions::OptionMap &Opts) {
+ Options.store(Opts, "UseAssignment", UseAssignment);
+}
+
+AST_MATCHER(FieldDecl, hasInClassInitializer) {
+ return Node.hasInClassInitializer();
+}
+
+void UseDefaultMemberInitCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(
+ cxxConstructorDecl(
+ isDefaultConstructor(),
+ forEachConstructorInitializer(allOf(
+ forField(unless(anyOf(isBitField(), hasInClassInitializer()))),
+ cxxCtorInitializer(isWritten(),
+ withInitializer(ignoringImplicit(anyOf(
+ integerLiteral(), floatLiteral(),
+ cxxBoolLiteral(), cxxNullPtrLiteralExpr(),
+ implicitValueInitExpr(), declRefExpr()))))
+ .bind("default")))),
+ this);
+
+ Finder->addMatcher(
+ cxxConstructorDecl(forEachConstructorInitializer(
+ allOf(forField(hasInClassInitializer()),
+ cxxCtorInitializer(
+ isWritten(), withInitializer(ignoringImplicit(anyOf(
+ integerLiteral(), floatLiteral(),
+ cxxBoolLiteral(), cxxNullPtrLiteralExpr(),
+ implicitValueInitExpr(), declRefExpr()))))
+ .bind("existing")))),
+ this);
+}
+
+void UseDefaultMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *Default = Result.Nodes.getNodeAs<CXXCtorInitializer>("default");
+ const auto *Existing = Result.Nodes.getNodeAs<CXXCtorInitializer>("existing");
+
+ if (Default)
+ checkDefaultInit(Result, Default);
+ else
+ checkExistingInit(Result, Existing);
+}
+
+void UseDefaultMemberInitCheck::checkDefaultInit(
+ const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
+ const FieldDecl *Field = Init->getMember();
+
+ SourceLocation FieldEnd =
+ Lexer::getLocForEndOfToken(Field->getSourceRange().getEnd(), 0,
+ *Result.SourceManager, getLangOpts());
+ SourceLocation LParenEnd = Lexer::getLocForEndOfToken(
+ Init->getLParenLoc(), 0, *Result.SourceManager, getLangOpts());
+ CharSourceRange InitRange =
+ CharSourceRange::getCharRange(LParenEnd, Init->getRParenLoc());
+
+ auto Diag =
+ diag(Field->getLocation(), "use default member initializer for %0")
+ << Field
+ << FixItHint::CreateInsertion(FieldEnd, UseAssignment ? " = " : "{")
+ << FixItHint::CreateInsertionFromRange(FieldEnd, InitRange);
+
+ if (UseAssignment && isa<ImplicitValueInitExpr>(Init->getInit()))
+ Diag << FixItHint::CreateInsertion(FieldEnd, getValueInit(Init));
+
+ if (!UseAssignment)
+ Diag << FixItHint::CreateInsertion(FieldEnd, "}");
+
+ Diag << FixItHint::CreateRemoval(Init->getSourceRange());
+}
+
+void UseDefaultMemberInitCheck::checkExistingInit(
+ const MatchFinder::MatchResult &Result, const CXXCtorInitializer *Init) {
+ const FieldDecl *Field = Init->getMember();
+
+ if (!sameValue(Field->getInClassInitializer(), Init->getInit()))
+ return;
+
+ diag(Init->getSourceLocation(), "member initializer for %0 is redundant")
+ << Field
+ << FixItHint::CreateRemoval(Init->getSourceRange());
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/modernize/ModernizeTidyModule.cpp
===================================================================
--- clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -23,6 +23,7 @@
#include "UseAutoCheck.h"
#include "UseBoolLiteralsCheck.h"
#include "UseDefaultCheck.h"
+#include "UseDefaultMemberInitCheck.h"
#include "UseEmplaceCheck.h"
#include "UseEqualsDeleteCheck.h"
#include "UseNullptrCheck.h"
@@ -57,6 +58,8 @@
CheckFactories.registerCheck<UseBoolLiteralsCheck>(
"modernize-use-bool-literals");
CheckFactories.registerCheck<UseDefaultCheck>("modernize-use-default");
+ CheckFactories.registerCheck<UseDefaultMemberInitCheck>(
+ "modernize-use-default-member-init");
CheckFactories.registerCheck<UseEmplaceCheck>("modernize-use-emplace");
CheckFactories.registerCheck<UseEqualsDeleteCheck>(
"modernize-use-equals-delete");
Index: clang-tidy/modernize/CMakeLists.txt
===================================================================
--- clang-tidy/modernize/CMakeLists.txt
+++ clang-tidy/modernize/CMakeLists.txt
@@ -17,6 +17,7 @@
UseAutoCheck.cpp
UseBoolLiteralsCheck.cpp
UseDefaultCheck.cpp
+ UseDefaultMemberInitCheck.cpp
UseEmplaceCheck.cpp
UseEqualsDeleteCheck.cpp
UseNullptrCheck.cpp
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits