On Tue, Dec 20, 2016 at 4:26 PM, Malcolm Parsons via cfe-commits <cfe-commits@lists.llvm.org> wrote: > 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
This appears to have broken one of the bots: http://bb.pgr.jp/builders/ninja-x64-msvc-RA-centos6/builds/33046 ~Aaron > > 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); > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits