[clang-tools-extra] r290202 - [clang-tidy] Add modernize-use-default-member-init check
Malcolm Parsons via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 20 13:26:07 PST 2016
Author: malcolm.parsons
Date: Tue Dec 20 15:26:07 2016
New Revision: 290202
URL: http://llvm.org/viewvc/llvm-project?rev=290202&view=rev
Log:
[clang-tidy] Add modernize-use-default-member-init check
Summary: Fixes PR18858
Reviewers: alexfh, hokein, aaron.ballman
Subscribers: JDevlieghere, Eugene.Zelenko, Prazek, mgorny, cfe-commits, modocache
Differential Revision: https://reviews.llvm.org/D26750
Added:
clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default-member-init.rst
clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
Modified: clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt?rev=290202&r1=290201&r2=290202&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/CMakeLists.txt Tue Dec 20 15:26:07 2016
@@ -16,6 +16,7 @@ add_clang_library(clangTidyModernizeModu
ShrinkToFitCheck.cpp
UseAutoCheck.cpp
UseBoolLiteralsCheck.cpp
+ UseDefaultMemberInitCheck.cpp
UseEmplaceCheck.cpp
UseEqualsDefaultCheck.cpp
UseEqualsDeleteCheck.cpp
Modified: clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp?rev=290202&r1=290201&r2=290202&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/modernize/ModernizeTidyModule.cpp Tue Dec 20 15:26:07 2016
@@ -22,6 +22,7 @@
#include "ShrinkToFitCheck.h"
#include "UseAutoCheck.h"
#include "UseBoolLiteralsCheck.h"
+#include "UseDefaultMemberInitCheck.h"
#include "UseEmplaceCheck.h"
#include "UseEqualsDefaultCheck.h"
#include "UseEqualsDeleteCheck.h"
@@ -56,6 +57,8 @@ public:
CheckFactories.registerCheck<UseAutoCheck>("modernize-use-auto");
CheckFactories.registerCheck<UseBoolLiteralsCheck>(
"modernize-use-bool-literals");
+ CheckFactories.registerCheck<UseDefaultMemberInitCheck>(
+ "modernize-use-default-member-init");
CheckFactories.registerCheck<UseEmplaceCheck>("modernize-use-emplace");
CheckFactories.registerCheck<UseEqualsDefaultCheck>("modernize-use-equals-default");
CheckFactories.registerCheck<UseEqualsDeleteCheck>(
Added: clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp?rev=290202&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.cpp Tue Dec 20 15:26:07 2016
@@ -0,0 +1,241 @@
+//===--- 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 getValueOfValueInit(const QualType InitType) {
+ switch (InitType->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:
+ switch (InitType->getAs<BuiltinType>()->getKind()) {
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ return "'\\0'";
+ case BuiltinType::WChar_U:
+ case BuiltinType::WChar_S:
+ return "L'\\0'";
+ case BuiltinType::Char16:
+ return "u'\\0'";
+ case BuiltinType::Char32:
+ return "U'\\0'";
+ default:
+ return "0";
+ }
+
+ case Type::STK_Floating:
+ switch (InitType->getAs<BuiltinType>()->getKind()) {
+ case BuiltinType::Half:
+ case BuiltinType::Float:
+ return "0.0f";
+ default:
+ return "0.0";
+ }
+
+ case Type::STK_FloatingComplex:
+ case Type::STK_IntegralComplex:
+ return getValueOfValueInit(
+ InitType->getAs<ComplexType>()->getElementType());
+ }
+ llvm_unreachable("Invalid scalar type kind");
+}
+
+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::CharacterLiteralClass:
+ return !cast<CharacterLiteral>(E)->getValue();
+ 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 *ignoreUnaryPlus(const Expr *E) {
+ auto *UnaryOp = dyn_cast<UnaryOperator>(E);
+ if (UnaryOp && UnaryOp->getOpcode() == UO_Plus)
+ return UnaryOp->getSubExpr();
+ return E;
+}
+
+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 = ignoreUnaryPlus(getInitializer(E1->IgnoreParenImpCasts()));
+ E2 = ignoreUnaryPlus(getInitializer(E2->IgnoreParenImpCasts()));
+
+ if (isZero(E1) && isZero(E2))
+ return true;
+
+ if (E1->getStmtClass() != E2->getStmtClass())
+ return false;
+
+ switch (E1->getStmtClass()) {
+ case Stmt::UnaryOperatorClass:
+ return sameValue(cast<UnaryOperator>(E1)->getSubExpr(),
+ cast<UnaryOperator>(E2)->getSubExpr());
+ case Stmt::CharacterLiteralClass:
+ return cast<CharacterLiteral>(E1)->getValue() ==
+ cast<CharacterLiteral>(E2)->getValue();
+ 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::StringLiteralClass:
+ return cast<StringLiteral>(E1)->getString() ==
+ cast<StringLiteral>(E2)->getString();
+ case Stmt::DeclRefExprClass:
+ return cast<DeclRefExpr>(E1)->getDecl() == cast<DeclRefExpr>(E2)->getDecl();
+ default:
+ 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) {
+ if (!getLangOpts().CPlusPlus11)
+ return;
+
+ auto Init =
+ anyOf(stringLiteral(), characterLiteral(), integerLiteral(),
+ unaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-")),
+ hasUnaryOperand(integerLiteral())),
+ floatLiteral(),
+ unaryOperator(anyOf(hasOperatorName("+"), hasOperatorName("-")),
+ hasUnaryOperand(floatLiteral())),
+ cxxBoolLiteral(), cxxNullPtrLiteralExpr(), implicitValueInitExpr(),
+ declRefExpr());
+
+ Finder->addMatcher(
+ cxxConstructorDecl(
+ isDefaultConstructor(), unless(isInstantiated()),
+ forEachConstructorInitializer(allOf(
+ forField(unless(anyOf(isBitField(), hasInClassInitializer()))),
+ cxxCtorInitializer(isWritten(),
+ withInitializer(ignoringImplicit(Init)))
+ .bind("default")))),
+ this);
+
+ Finder->addMatcher(
+ cxxConstructorDecl(
+ unless(ast_matchers::isTemplateInstantiation()),
+ forEachConstructorInitializer(
+ allOf(forField(hasInClassInitializer()),
+ cxxCtorInitializer(isWritten(),
+ withInitializer(ignoringImplicit(Init)))
+ .bind("existing")))),
+ this);
+}
+
+void UseDefaultMemberInitCheck::check(const MatchFinder::MatchResult &Result) {
+ if (const auto *Default =
+ Result.Nodes.getNodeAs<CXXCtorInitializer>("default"))
+ checkDefaultInit(Result, Default);
+ else if (const auto *Existing =
+ Result.Nodes.getNodeAs<CXXCtorInitializer>("existing"))
+ checkExistingInit(Result, Existing);
+ else
+ llvm_unreachable("Bad Callback. No node provided.");
+}
+
+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, getValueOfValueInit(Init->getInit()->getType()));
+
+ 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
Added: clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.h?rev=290202&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/modernize/UseDefaultMemberInitCheck.h Tue Dec 20 15:26:07 2016
@@ -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
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=290202&r1=290201&r2=290202&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Tue Dec 20 15:26:07 2016
@@ -108,6 +108,12 @@ Improvements to clang-tidy
- The modernize-use-default check has been renamed to `modernize-use-equals-default
<http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-equals-default.html>`_.
+
+- 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
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=290202&r1=290201&r2=290202&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Tue Dec 20 15:26:07 2016
@@ -110,6 +110,7 @@ Clang-Tidy Checks
modernize-shrink-to-fit
modernize-use-auto
modernize-use-bool-literals
+ modernize-use-default-member-init
modernize-use-emplace
modernize-use-equals-default
modernize-use-equals-delete
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default-member-init.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default-member-init.rst?rev=290202&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default-member-init.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/modernize-use-default-member-init.rst Tue Dec 20 15:26:07 2016
@@ -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 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'.
+
+.. 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;
+ };
Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init-assignment.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init-assignment.cpp?rev=290202&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init-assignment.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init-assignment.cpp Tue Dec 20 15:26:07 2016
@@ -0,0 +1,184 @@
+// 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 PositiveValueChar {
+ PositiveValueChar() : c0(), c1(), c2(), c3() {}
+ // CHECK-FIXES: PositiveValueChar() {}
+ const char c0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use default member initializer for 'c0' [modernize-use-default-member-init]
+ // CHECK-FIXES: const char c0 = '\0';
+ wchar_t c1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use default member initializer for 'c1'
+ // CHECK-FIXES: wchar_t c1 = L'\0';
+ char16_t c2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c2'
+ // CHECK-FIXES: char16_t c2 = u'\0';
+ char32_t c3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c3'
+ // CHECK-FIXES: char32_t c3 = U'\0';
+};
+
+struct PositiveChar {
+ PositiveChar() : d('a') {}
+ // CHECK-FIXES: PositiveChar() {}
+ char d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'd'
+ // CHECK-FIXES: char d = 'a';
+};
+
+struct PositiveValueInt {
+ PositiveValueInt() : i() {}
+ // CHECK-FIXES: PositiveValueInt() {}
+ const int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use default member initializer for 'i'
+ // 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'
+ // CHECK-FIXES: int j = 1;
+};
+
+struct PositiveUnaryMinusInt {
+ PositiveUnaryMinusInt() : j(-1) {}
+ // CHECK-FIXES: PositiveUnaryMinusInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j = -1;
+};
+
+struct PositiveUnaryPlusInt {
+ PositiveUnaryPlusInt() : j(+1) {}
+ // CHECK-FIXES: PositiveUnaryPlusInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j = +1;
+};
+
+struct PositiveValueComplexInt {
+ PositiveValueComplexInt() : i() {}
+ // CHECK-FIXES: PositiveValueComplexInt() {}
+ _Complex int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use default member initializer for 'i'
+ // CHECK-FIXES: _Complex int i = 0;
+};
+
+struct PositiveValueFloat {
+ PositiveValueFloat() : f() {}
+ // CHECK-FIXES: PositiveValueFloat() {}
+ float f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 'f'
+ // CHECK-FIXES: float f = 0.0f;
+};
+
+struct PositiveValueDouble {
+ PositiveValueDouble() : d() {}
+ // CHECK-FIXES: PositiveValueDouble() {}
+ double d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'd'
+ // 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'
+ // CHECK-FIXES: double f = 2.5463e43;
+};
+
+struct PositiveValueComplexFloat {
+ PositiveValueComplexFloat() : f() {}
+ // CHECK-FIXES: PositiveValueComplexFloat() {}
+ _Complex float f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use default member initializer for 'f'
+ // CHECK-FIXES: _Complex float f = 0.0f;
+};
+
+struct PositiveValueComplexDouble {
+ PositiveValueComplexDouble() : f() {}
+ // CHECK-FIXES: PositiveValueComplexDouble() {}
+ _Complex double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use default member initializer for 'f'
+ // CHECK-FIXES: _Complex double f = 0.0;
+};
+
+struct PositiveUnaryMinusDouble {
+ PositiveUnaryMinusDouble() : f(-2.5463e43) {}
+ // CHECK-FIXES: PositiveUnaryMinusDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // CHECK-FIXES: double f = -2.5463e43;
+};
+
+struct PositiveUnaryPlusDouble {
+ PositiveUnaryPlusDouble() : f(+2.5463e43) {}
+ // CHECK-FIXES: PositiveUnaryPlusDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // 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'
+ // 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'
+ // 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'
+ // 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'
+ // 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'
+ // CHECK-FIXES: Enum e = Foo;
+};
+
+struct PositiveString {
+ PositiveString() : s("foo") {}
+ // CHECK-FIXES: PositiveString() {}
+ const char *s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use default member initializer for 's'
+ // CHECK-FIXES: const char *s = "foo";
+};
+
+template <typename T>
+struct NegativeTemplate {
+ NegativeTemplate() : t() {}
+ T t;
+};
+
+NegativeTemplate<int> nti;
+NegativeTemplate<double> ntd;
Added: clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init.cpp?rev=290202&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/modernize-use-default-member-init.cpp Tue Dec 20 15:26:07 2016
@@ -0,0 +1,376 @@
+// RUN: %check_clang_tidy %s modernize-use-default-member-init %t -- -- -std=c++11
+
+struct S {
+};
+
+struct PositiveValueChar {
+ PositiveValueChar() : c0(), c1(), c2(), c3() {}
+ // CHECK-FIXES: PositiveValueChar() {}
+ const char c0;
+ // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use default member initializer for 'c0' [modernize-use-default-member-init]
+ // CHECK-FIXES: const char c0{};
+ wchar_t c1;
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: use default member initializer for 'c1'
+ // CHECK-FIXES: wchar_t c1{};
+ char16_t c2;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c2'
+ // CHECK-FIXES: char16_t c2{};
+ char32_t c3;
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use default member initializer for 'c3'
+ // CHECK-FIXES: char32_t c3{};
+};
+
+struct PositiveChar {
+ PositiveChar() : d('a') {}
+ // CHECK-FIXES: PositiveChar() {}
+ char d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use default member initializer for 'd'
+ // CHECK-FIXES: char d{'a'};
+};
+
+struct PositiveValueInt {
+ PositiveValueInt() : i() {}
+ // CHECK-FIXES: PositiveValueInt() {}
+ const int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use default member initializer for 'i'
+ // 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'
+ // CHECK-FIXES: int j{1};
+};
+
+struct PositiveUnaryMinusInt {
+ PositiveUnaryMinusInt() : j(-1) {}
+ // CHECK-FIXES: PositiveUnaryMinusInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j{-1};
+};
+
+struct PositiveUnaryPlusInt {
+ PositiveUnaryPlusInt() : j(+1) {}
+ // CHECK-FIXES: PositiveUnaryPlusInt() {}
+ int j;
+ // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use default member initializer for 'j'
+ // CHECK-FIXES: int j{+1};
+};
+
+struct PositiveValueComplexInt {
+ PositiveValueComplexInt() : i() {}
+ // CHECK-FIXES: PositiveValueComplexInt() {}
+ _Complex int i;
+ // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use default member initializer for 'i'
+ // CHECK-FIXES: _Complex int i{};
+};
+
+struct PositiveValueFloat {
+ PositiveValueFloat() : f() {}
+ // CHECK-FIXES: PositiveValueFloat() {}
+ float f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use default member initializer for 'f'
+ // CHECK-FIXES: float f{};
+};
+
+struct PositiveValueDouble {
+ PositiveValueDouble() : d() {}
+ // CHECK-FIXES: PositiveValueDouble() {}
+ double d;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'd'
+ // 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'
+ // CHECK-FIXES: double f{2.5463e43};
+};
+
+struct PositiveValueComplexFloat {
+ PositiveValueComplexFloat() : f() {}
+ // CHECK-FIXES: PositiveValueComplexFloat() {}
+ _Complex float f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: use default member initializer for 'f'
+ // CHECK-FIXES: _Complex float f{};
+};
+
+struct PositiveValueComplexDouble {
+ PositiveValueComplexDouble() : f() {}
+ // CHECK-FIXES: PositiveValueComplexDouble() {}
+ _Complex double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: use default member initializer for 'f'
+ // CHECK-FIXES: _Complex double f{};
+};
+
+struct PositiveUnaryMinusDouble {
+ PositiveUnaryMinusDouble() : f(-2.5463e43) {}
+ // CHECK-FIXES: PositiveUnaryMinusDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // CHECK-FIXES: double f{-2.5463e43};
+};
+
+struct PositiveUnaryPlusDouble {
+ PositiveUnaryPlusDouble() : f(+2.5463e43) {}
+ // CHECK-FIXES: PositiveUnaryPlusDouble() {}
+ double f;
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use default member initializer for 'f'
+ // 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'
+ // 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'
+ // 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'
+ // 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'
+ // 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'
+ // CHECK-FIXES: Enum e{Foo};
+};
+
+struct PositiveString {
+ PositiveString() : s("foo") {}
+ // CHECK-FIXES: PositiveString() {}
+ const char *s;
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use default member initializer for 's'
+ // CHECK-FIXES: const char *s{"foo"};
+};
+
+template <typename T>
+struct NegativeTemplate {
+ NegativeTemplate() : t() {}
+ T t;
+};
+
+NegativeTemplate<int> nti;
+NegativeTemplate<double> ntd;
+
+struct NegativeDefaultMember {
+ NegativeDefaultMember() {}
+ 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 ExistingChar {
+ ExistingChar(short) : e1(), e2(), e3(), e4() {}
+ // 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
+ // CHECK-MESSAGES: :[[@LINE-3]]:37: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingChar(short) : e4() {}
+ ExistingChar(int) : e1(0), e2(0), e3(0), e4(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:30: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:37: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingChar(int) : e4(0) {}
+ ExistingChar(long) : e1('\0'), e2('\0'), e3('\0'), e4('\0') {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:44: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingChar(long) : e4('\0') {}
+ ExistingChar(char) : e1('a'), e2('a'), e3('a'), e4('a') {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:51: warning: member initializer for 'e4' is redundant
+ // CHECK-FIXES: ExistingChar(char) : e1('a'), e2('a'), e3('a') {}
+ char e1{};
+ char e2 = 0;
+ char e3 = '\0';
+ char e4 = 'a';
+};
+
+struct ExistingInt {
+ ExistingInt(short) : e1(), e2(), e3(), e4(), e5(), e6() {}
+ // 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
+ // CHECK-FIXES: ExistingInt(short) : e3(), e4(), e5(), e6() {}
+ ExistingInt(int) : e1(0), e2(0), e3(0), e4(0), e5(0), e6(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:29: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingInt(int) : e3(0), e4(0), e5(0), e6(0) {}
+ ExistingInt(long) : e1(5), e2(5), e3(5), e4(5), e5(5), e6(5) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:37: warning: member initializer for 'e3' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:44: warning: member initializer for 'e4' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:58: warning: member initializer for 'e6' is redundant
+ // CHECK-FIXES: ExistingInt(long) : e1(5), e2(5), e5(5) {}
+ ExistingInt(char) : e1(-5), e2(-5), e3(-5), e4(-5), e5(-5), e6(-5) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:55: warning: member initializer for 'e5' is redundant
+ // CHECK-FIXES: ExistingInt(char) : e1(-5), e2(-5), e3(-5), e4(-5), e6(-5) {}
+ int e1{};
+ int e2 = 0;
+ int e3 = {5};
+ int e4 = 5;
+ int e5 = -5;
+ int e6 = +5;
+};
+
+struct ExistingDouble {
+ ExistingDouble(short) : e1(), e2(), e3(), e4(), e5() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingDouble(short) : e3(), e4(), e5() {}
+ ExistingDouble(int) : e1(0.0), e2(0.0), e3(0.0), e4(0.0), e5(0.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingDouble(int) : e3(0.0), e4(0.0), e5(0.0) {}
+ ExistingDouble(long) : e1(5.0), e2(5.0), e3(5.0), e4(5.0), e5(5.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:44: warning: member initializer for 'e3' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:62: warning: member initializer for 'e5' is redundant
+ // CHECK-FIXES: ExistingDouble(long) : e1(5.0), e2(5.0), e4(5.0) {}
+ ExistingDouble(char) : e1(-5.0), e2(-5.0), e3(-5.0), e4(-5.0), e5(-5.0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:56: warning: member initializer for 'e4' is redundant
+ // CHECK-FIXES: ExistingDouble(char) : e1(-5.0), e2(-5.0), e3(-5.0), e5(-5.0) {}
+ double e1{};
+ double e2 = 0.0;
+ double e3 = 5.0;
+ double e4 = -5.0;
+ double e5 = +5.0;
+};
+
+struct ExistingBool {
+ ExistingBool(short) : e1(), e2(), e3() {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:31: warning: member initializer for 'e2' is redundant
+ // 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
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+ // 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
+ // 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
+ // CHECK-FIXES: ExistingEnum(short) : e2(Foo) {}
+ ExistingEnum(int) : e1(Bar), e2(Bar) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: member initializer for 'e2' is redundant
+ // 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
+ // CHECK-MESSAGES: :[[@LINE-2]]:34: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:40: warning: member initializer for 'e3' is redundant
+ // 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
+ // CHECK-MESSAGES: :[[@LINE-2]]:33: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:40: warning: member initializer for 'e3' is redundant
+ // 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
+ // CHECK-MESSAGES: :[[@LINE-2]]:40: warning: member initializer for 'e2' is redundant
+ // CHECK-MESSAGES: :[[@LINE-3]]:53: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingPointer(long) : e4(&e2) {}
+ int *e1{};
+ int *e2 = 0;
+ int *e3 = nullptr;
+ int **e4 = &e1;
+};
+
+struct ExistingString {
+ ExistingString(short) : e1(), e2(), e3(), e4() {}
+ // 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
+ // CHECK-FIXES: ExistingString(short) : e3(), e4() {}
+ ExistingString(int) : e1(0), e2(0), e3(0), e4(0) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:32: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingString(int) : e3(0), e4(0) {}
+ ExistingString(long) : e1(nullptr), e2(nullptr), e3(nullptr), e4(nullptr) {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: member initializer for 'e1' is redundant
+ // CHECK-MESSAGES: :[[@LINE-2]]:39: warning: member initializer for 'e2' is redundant
+ // CHECK-FIXES: ExistingString(long) : e3(nullptr), e4(nullptr) {}
+ ExistingString(char) : e1("foo"), e2("foo"), e3("foo"), e4("foo") {}
+ // CHECK-MESSAGES: :[[@LINE-1]]:48: warning: member initializer for 'e3' is redundant
+ // CHECK-FIXES: ExistingString(char) : e1("foo"), e2("foo"), e4("foo") {}
+ const char *e1{};
+ const char *e2 = nullptr;
+ const char *e3 = "foo";
+ const char *e4 = "bar";
+};
+
+template <typename T>
+struct NegativeTemplateExisting {
+ NegativeTemplateExisting(int) : t(0) {}
+ T t{};
+};
+
+NegativeTemplateExisting<int> ntei(0);
+NegativeTemplateExisting<double> nted(0);
More information about the cfe-commits
mailing list