[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