https://github.com/AMS21 updated https://github.com/llvm/llvm-project/pull/91124
>From 84c8e546c0826ddcf9c580b9368541670ed05068 Mon Sep 17 00:00:00 2001 From: AMS21 <ams21.git...@gmail.com> Date: Tue, 16 Apr 2024 08:56:13 +0200 Subject: [PATCH] [clang-tidy] Add `modernize-use-uniform-initializer` check Finds usage of C-Style initialization that can be rewritten with C++-11 uniform initializers. --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../modernize/UseUniformInitializerCheck.cpp | 320 ++++++++++++++++++ .../modernize/UseUniformInitializerCheck.h | 37 ++ .../clang-tidy/utils/LexerUtils.cpp | 23 ++ .../clang-tidy/utils/LexerUtils.h | 4 + clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 1 + .../modernize/use-uniform-initializer.rst | 34 ++ .../modernize/use-uniform-initializer.cpp | 174 ++++++++++ 10 files changed, 603 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseUniformInitializerCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseUniformInitializerCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-uniform-initializer.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-uniform-initializer.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 4f68c487cac9d4..4ca56cb26bd433 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -48,6 +48,7 @@ add_clang_library(clangTidyModernizeModule UseTrailingReturnTypeCheck.cpp UseTransparentFunctorsCheck.cpp UseUncaughtExceptionsCheck.cpp + UseUniformInitializerCheck.cpp UseUsingCheck.cpp LINK_LIBS diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index 18607593320635..35fb2bdf042ceb 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -49,6 +49,7 @@ #include "UseTrailingReturnTypeCheck.h" #include "UseTransparentFunctorsCheck.h" #include "UseUncaughtExceptionsCheck.h" +#include "UseUniformInitializerCheck.h" #include "UseUsingCheck.h" using namespace clang::ast_matchers; @@ -121,6 +122,8 @@ class ModernizeModule : public ClangTidyModule { "modernize-use-transparent-functors"); CheckFactories.registerCheck<UseUncaughtExceptionsCheck>( "modernize-use-uncaught-exceptions"); + CheckFactories.registerCheck<UseUniformInitializerCheck>( + "modernize-use-uniform-initializer"); CheckFactories.registerCheck<UseUsingCheck>("modernize-use-using"); } }; diff --git a/clang-tools-extra/clang-tidy/modernize/UseUniformInitializerCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseUniformInitializerCheck.cpp new file mode 100644 index 00000000000000..204a42d8c81895 --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseUniformInitializerCheck.cpp @@ -0,0 +1,320 @@ +//===--- UseUniformInitializerCheck.cpp - clang-tidy ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "UseUniformInitializerCheck.h" +#include "../utils/LexerUtils.h" +#include "clang/Tooling/FixIt.h" + +AST_MATCHER(clang::VarDecl, isVarOldStyleInitializer) { + // If it doesn't have any initializer the initializer style is not defined. + if (!Node.hasInit()) + return false; + + const clang::VarDecl::InitializationStyle InitStyle = Node.getInitStyle(); + + return InitStyle == clang::VarDecl::InitializationStyle::CInit || + InitStyle == clang::VarDecl::InitializationStyle::CallInit; +} + +AST_MATCHER(clang::FieldDecl, isFieldOldStyleInitializer) { + // If it doesn't have any initializer the initializer style is not defined. + if (!Node.hasInClassInitializer() || Node.getInClassInitializer() == nullptr) + return false; + + const clang::InClassInitStyle InitStyle = Node.getInClassInitStyle(); + + return InitStyle == clang::InClassInitStyle::ICIS_CopyInit; +} + +AST_MATCHER(clang::CXXCtorInitializer, isCStyleInitializer) { + const clang::Expr *Init = Node.getInit(); + if (Init == nullptr) + return false; + + return !llvm::isa<clang::InitListExpr>(Init); +} + +using namespace clang::ast_matchers; + +namespace clang::tidy::modernize { + +namespace { + +constexpr const StringRef VarDeclID = "VarDecl"; +constexpr const StringRef FieldDeclId = "FieldDecl"; +constexpr const StringRef CtorInitID = "CtorInit"; + +constexpr const StringRef CStyleWarningMessage = + "Use uniform initializer instead of C-style initializer"; + +constexpr StringRef +getInitializerStyleName(VarDecl::InitializationStyle InitStyle) { + switch (InitStyle) { + case VarDecl::InitializationStyle::CInit: + return "C"; + + case VarDecl::InitializationStyle::CallInit: + return "call"; + + default: + llvm_unreachable("Invalid initializer style!"); + } +} + +SourceRange getParenLocationsForCallInit(const Expr *InitExpr, + const SourceManager &SM, + const LangOptions &LangOpts) { + // We need to handle 'CXXConstructExpr' differently + if (isa<CXXConstructExpr>(InitExpr)) + return cast<CXXConstructExpr>(InitExpr)->getParenOrBraceRange(); + + // If the init expression itself is a 'ParenExpr' then + // 'InitExpr->getBeginLoc()' will already point to a '(' which is not the + // opening paren of the 'CallInit' expression. So it that case we need to + // start one character before that. + const bool NeedOffsetForOpenParen = [&]() { + if (!isa<ParenExpr>(InitExpr)) + return false; + + const clang::StringRef CharBeforeParenExpr = + Lexer::getSourceText(CharSourceRange::getCharRange( + InitExpr->getBeginLoc().getLocWithOffset(-1), + InitExpr->getBeginLoc()), + SM, LangOpts); + + return llvm::isSpace(CharBeforeParenExpr[0]); + }(); + + const SourceLocation OpenParenLoc = utils::lexer::findPreviousTokenKind( + NeedOffsetForOpenParen ? InitExpr->getBeginLoc().getLocWithOffset(-1) + : InitExpr->getBeginLoc(), + SM, LangOpts, tok::l_paren); + const SourceLocation CloseParenLoc = utils::lexer::findNextTokenKind( + InitExpr->getEndLoc(), SM, LangOpts, tok::r_paren); + + return {OpenParenLoc, CloseParenLoc}; +} + +const BuiltinType *getBuiltinType(const Expr *Expr) { + assert(Expr); + return Expr->getType().getCanonicalType().getTypePtr()->getAs<BuiltinType>(); +} + +bool castRequiresStaticCast(const ImplicitCastExpr *CastExpr) { + const auto *FromExpr = CastExpr->getSubExpr(); + + if (CastExpr->isInstantiationDependent() || + FromExpr->isInstantiationDependent()) + return false; + if (getBuiltinType(CastExpr) == getBuiltinType(FromExpr)) + return false; + + switch (CastExpr->getCastKind()) { + case CastKind::CK_BaseToDerived: + case CastKind::CK_DerivedToBaseMemberPointer: + case CastKind::CK_IntegralCast: + case CastKind::CK_FloatingToIntegral: + return true; + + default: + return false; + } +} + +std::string buildReplacementString(const Expr *InitExpr, + const ASTContext &Context) { + // TODO: This function does not correctly handle the case where you have in + // 'ImplicitCastExpr' as an argument for a 'CXXConstructExpr'. + // In that case the generated code will not compile due to missing explicit + // cast of the sub expression. + + const SourceManager &SM = Context.getSourceManager(); + const LangOptions &LangOpts = Context.getLangOpts(); + + const StringRef InitExprStr = [&]() { + if (isa<CXXConstructExpr>(InitExpr)) { + const auto *ConstructExpr = llvm::cast<CXXConstructExpr>(InitExpr); + + const SourceRange ParenRange = ConstructExpr->getParenOrBraceRange(); + if (ParenRange.isValid()) + return Lexer::getSourceText( + CharSourceRange::getCharRange( + ParenRange.getBegin().getLocWithOffset(1), + ParenRange.getEnd()), + SM, LangOpts) + .trim(); + + // In case the ParenRange is invalid we use Begin/EndLoc + const SourceLocation BeginLocation = ConstructExpr->getBeginLoc(); + const SourceLocation EndLocation = ConstructExpr->getEndLoc(); + + return Lexer::getSourceText( + CharSourceRange::getCharRange(BeginLocation, + EndLocation.getLocWithOffset(1)), + SM, LangOpts) + .trim(); + } + + return tooling::fixit::getText(*InitExpr, Context); + }(); + + // For some 'ImplicitCastExpr' we need to add an extra 'static_cast<T>' around + // the expression since implicit conversions are not allowed with uniform + // initializer and otherwise will lead to compile errors + if (isa<ImplicitCastExpr>(InitExpr)) { + const auto *CastExpr = llvm::cast<ImplicitCastExpr>(InitExpr); + + if (castRequiresStaticCast(CastExpr)) { + const QualType Type = CastExpr->getType().getUnqualifiedType(); + + return ("{static_cast<" + Type.getAsString() + ">(" + InitExprStr + ")}") + .str(); + } + } + + // Otherwise just add the braces around the expression + return ("{" + InitExprStr + "}").str(); +} + +} // namespace + +void UseUniformInitializerCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(varDecl(isVarOldStyleInitializer(), unless(parmVarDecl())) + .bind(VarDeclID), + this); + Finder->addMatcher(fieldDecl(isFieldOldStyleInitializer()).bind(FieldDeclId), + this); + Finder->addMatcher(cxxCtorInitializer(isCStyleInitializer()).bind(CtorInitID), + this); +} + +void UseUniformInitializerCheck::check(const MatchFinder::MatchResult &Result) { + const SourceManager &SM = *Result.SourceManager; + const ASTContext &Context = *Result.Context; + const LangOptions &LangOpts = Context.getLangOpts(); + + const auto *VDecl = Result.Nodes.getNodeAs<VarDecl>(VarDeclID); + const auto *FDecl = Result.Nodes.getNodeAs<FieldDecl>(FieldDeclId); + const auto *CtorInit = Result.Nodes.getNodeAs<CXXCtorInitializer>(CtorInitID); + + // Handle variable declarations + if (VDecl != nullptr) { + const auto *InitExpr = VDecl->getInit(); + assert(InitExpr); + + // If the expression is an 'ExprWithCleanups' just get the subexpression + if (isa<ExprWithCleanups>(InitExpr)) + InitExpr = llvm::cast<ExprWithCleanups>(InitExpr)->getSubExpr(); + + const VarDecl::InitializationStyle InitStyle = VDecl->getInitStyle(); + + // Check for the special case that a default constructor with no arguments + // is used + // Example: struct A{}; A a; + const auto *ConstructorExpr = dyn_cast_or_null<CXXConstructExpr>(InitExpr); + if (ConstructorExpr && ConstructorExpr->getNumArgs() == 0) + return; + + // Ignore declarations inside a 'CXXForRangeStmt' + if (VDecl->isCXXForRangeDecl()) + return; + + if (InitStyle == VarDecl::InitializationStyle::CInit) { + const SourceLocation EqualLoc = utils::lexer::findPreviousTokenKind( + InitExpr->getBeginLoc(), SM, LangOpts, tok::equal); + if (!EqualLoc.isValid()) + return; + + auto Diag = + diag(EqualLoc, + "Use uniform initializer instead of %0-style initializer") + << getInitializerStyleName(InitStyle); + + // If we have a C-style initializer with an 'InitListExpr', we only need + // to remove the '=' + // For example: 'int a = {0};' + if (isa<InitListExpr>(InitExpr)) + Diag << FixItHint::CreateRemoval(EqualLoc); + else { + // Otherwise with a normal c-style initializer we also need to add '{' + // and '}' + // For example: 'int a = 0;' + const std::string ReplacementText = + buildReplacementString(InitExpr, Context); + + Diag << FixItHint::CreateReplacement( + SourceRange{EqualLoc, InitExpr->getEndLoc()}, ReplacementText); + } + } else if (InitStyle == VarDecl::InitializationStyle::CallInit) { + const SourceRange ParenRange = + getParenLocationsForCallInit(InitExpr, SM, LangOpts); + if (ParenRange.isInvalid()) + return; + + const std::string ReplacementString = + buildReplacementString(InitExpr, Context); + + diag(ParenRange.getBegin(), + "Use uniform initializer instead of %0-style initializer") + << getInitializerStyleName(InitStyle) + << FixItHint::CreateReplacement(ParenRange, ReplacementString); + } else { + llvm_unreachable("Invalid initializer style!"); + } + } + // Handle field declarations + else if (FDecl != nullptr) { + const auto *InitExpr = FDecl->getInClassInitializer(); + assert(InitExpr); + + const SourceLocation EqualLoc = utils::lexer::findPreviousTokenKind( + InitExpr->getBeginLoc(), SM, LangOpts, tok::equal); + if (!EqualLoc.isValid()) + return; + + if (isa<InitListExpr>(InitExpr)) + // If we have a C-style initializer with an 'InitListExpr', we only need + // to remove the '=' + diag(EqualLoc, CStyleWarningMessage) + << FixItHint::CreateRemoval(EqualLoc); + else { + // Otherwise with a normal c-style initializer we also need to add '{' and + // '}' and rewrite the initializer + const StringRef InitExprStr = tooling::fixit::getText(*InitExpr, Context); + + const std::string ReplacementText = ("{" + InitExprStr + "}").str(); + + diag(EqualLoc, CStyleWarningMessage) << FixItHint::CreateReplacement( + SourceRange{EqualLoc, InitExpr->getEndLoc()}, ReplacementText); + } + } + // Otherwise must be a CXXCtorInitializer + else { + assert(CtorInit != nullptr); + + const auto *InitExpr = CtorInit->getInit(); + assert(InitExpr); + + const SourceLocation LParenLoc = CtorInit->getLParenLoc(); + const SourceLocation RParenLoc = CtorInit->getRParenLoc(); + + if (!LParenLoc.isValid() || !RParenLoc.isValid()) + return; + + if (LParenLoc == RParenLoc) + return; + + const std::string ReplacementString = + buildReplacementString(InitExpr, Context); + + diag(LParenLoc, CStyleWarningMessage) << FixItHint::CreateReplacement( + SourceRange{LParenLoc, RParenLoc}, ReplacementString); + } +} + +} // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseUniformInitializerCheck.h b/clang-tools-extra/clang-tidy/modernize/UseUniformInitializerCheck.h new file mode 100644 index 00000000000000..8263c8c3d759fc --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseUniformInitializerCheck.h @@ -0,0 +1,37 @@ +//===--- UseUniformInitializerCheck.h - clang-tidy --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEUNIFORMINITIALIZERCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEUNIFORMINITIALIZERCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::modernize { + +/// Finds C-Style initializers and converts them to uniform initializers. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-uniform-initializer.html +class UseUniformInitializerCheck : public ClangTidyCheck { +public: + UseUniformInitializerCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus11; + } + std::optional<TraversalKind> getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } + + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace clang::tidy::modernize + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEUNIFORMINITIALIZERCHECK_H diff --git a/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp b/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp index df2b0bef576ca3..88eb25e3828314 100644 --- a/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp +++ b/clang-tools-extra/clang-tidy/utils/LexerUtils.cpp @@ -84,6 +84,29 @@ SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM, return findNextAnyTokenKind(Start, SM, LangOpts, tok::comma, tok::semi); } +SourceLocation findNextTokenKind(SourceLocation Start, const SourceManager &SM, + const LangOptions &LangOpts, + tok::TokenKind TK) { + while (true) { + std::optional<Token> CurrentToken = + Lexer::findNextToken(Start, SM, LangOpts); + + if (!CurrentToken) + return {}; + + Token PotentialMatch = *CurrentToken; + if (PotentialMatch.is(TK)) + return PotentialMatch.getLocation(); + + // If we reach the end of the file, and eof is not the target token, we stop + // the loop, otherwise we will get infinite loop (findNextToken will return + // eof on eof). + if (PotentialMatch.is(tok::eof)) + return {}; + Start = PotentialMatch.getLastLoc(); + } +} + std::optional<Token> findNextTokenIncludingComments(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts) { diff --git a/clang-tools-extra/clang-tidy/utils/LexerUtils.h b/clang-tools-extra/clang-tidy/utils/LexerUtils.h index ea9bd512b68b8f..66e6163008a207 100644 --- a/clang-tools-extra/clang-tidy/utils/LexerUtils.h +++ b/clang-tools-extra/clang-tidy/utils/LexerUtils.h @@ -89,6 +89,10 @@ SourceLocation findNextAnyTokenKind(SourceLocation Start, } } +SourceLocation findNextTokenKind(SourceLocation Start, const SourceManager &SM, + const LangOptions &LangOpts, + tok::TokenKind TK); + std::optional<Token> findNextTokenIncludingComments(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts); diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 8d028f8863cb7a..330a8b3017470e 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -98,6 +98,12 @@ Improvements to clang-tidy New checks ^^^^^^^^^^ +- New :doc:`modernize-use-uniform-initializer + <clang-tidy/checks/modernize/use-uniform-initializer>` check. + + Finds usage of C-Style initialization that can be rewritten with + C++-11 uniform initializers. + New check aliases ^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index a931ebf025a10e..0367c95a774820 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -310,6 +310,7 @@ Clang-Tidy Checks :doc:`modernize-use-trailing-return-type <modernize/use-trailing-return-type>`, "Yes" :doc:`modernize-use-transparent-functors <modernize/use-transparent-functors>`, "Yes" :doc:`modernize-use-uncaught-exceptions <modernize/use-uncaught-exceptions>`, "Yes" + :doc:`modernize-use-uniform-initializer <modernize/use-uniform-initializer>`, "Yes" :doc:`modernize-use-using <modernize/use-using>`, "Yes" :doc:`mpi-buffer-deref <mpi/buffer-deref>`, "Yes" :doc:`mpi-type-mismatch <mpi/type-mismatch>`, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-uniform-initializer.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-uniform-initializer.rst new file mode 100644 index 00000000000000..eda11e060ed2c4 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-uniform-initializer.rst @@ -0,0 +1,34 @@ +.. title:: clang-tidy - modernize-use-uniform-initializer + +modernize-use-uniform-initializer +================================= + +Finds usage of C-Style initialization that can be rewritten with +C++-11 uniform initializers. + +Example +------- + +.. code-block:: c++ + + int foo = 21; + int bar(42); + + struct Baz { + Baz() : x(3) {} + + int x; + }; + +transforms to: + +.. code-block:: c++ + + int foo{21}; + int bar{42}; + + struct Baz { + Baz() : x{3} {} + + int x; + }; diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-uniform-initializer.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-uniform-initializer.cpp new file mode 100644 index 00000000000000..608af82065a935 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-uniform-initializer.cpp @@ -0,0 +1,174 @@ +// RUN: %check_clang_tidy -std=c++11 %s modernize-use-uniform-initializer %t + +int cinit_0 = 0; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int cinit_0 {0}; + +int cinit_1=0; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int cinit_1{0}; + +int callinit_0(0); +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int callinit_0{0}; + +int callinit_1 ( 0 ); +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int callinit_1 {0}; + +int callinit_2 ( ((3 + 1 + 4) + 1 + 5) ); +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int callinit_2 {((3 + 1 + 4) + 1 + 5)}; + +int callinit_3((9-2)+(6+5)); +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int callinit_3{(9-2)+(6+5)}; + +int callinit_4 ((3 * 5 + (8 - 9) )); +// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int callinit_4 {(3 * 5 + (8 - 9) )}; + +int callinit_5((7 + (-9))); +// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int callinit_5{(7 + (-9))}; + +int mixed_0 = {0}; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int mixed_0 {0}; + +int mixed_1={0}; +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int mixed_1{0}; + +int noinit; + +int correct_0{0}; + +int correct_1 {0}; + +struct CInitList_0 { + CInitList_0() : x(0) {} + // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] + // CHECK-FIXES: CInitList_0() : x{0} {} + + int x; +}; + +struct CInitList_1 { + CInitList_1():x(0) {} + // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] + // CHECK-FIXES: CInitList_1():x{0} {} + + int x; +}; + +struct CInitList_2 { + CInitList_2() : x ( 0 ) {} + // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] + // CHECK-FIXES: CInitList_2() : x {0} {} + + int x; +}; + +struct Correct_0 { + Correct_0() : x{0} {} + + int x; +}; + +struct Correct_1 { + Correct_1():x{0} {} + + int x; +}; + +struct InClassInitializers { + int cinit_0 = 0; + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] + // CHECK-FIXES: int cinit_0 {0}; + + int cinit_1=0; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] + // CHECK-FIXES: int cinit_1{0}; + + int mixed_0 = {0}; + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] + // CHECK-FIXES: int mixed_0 {0}; + + int mixed_1={0}; + // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] + // CHECK-FIXES: int mixed_1{0}; + + int noinit; + + int correct_0 {0}; + + int correct_1{0}; +}; + +// Defaulted function arguments cannot use the uniform initializer +void f(int x = 0) {} + +struct A { + A() = default; + A(int) {} + A(int, int) {} +}; + +A a_0; +A a_1{}; +A a_2(); // This is not a variable declaration it is actually a function definition (most vexing parse) +A a_3{21}; +A a_4{ 21 }; +A a_5(42); +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: A a_5{42}; +A a_6 ( 42 ); +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: A a_6 {42}; +A a_7{0, 1}; +A a_8{ 0, 1 }; +A a_9(0, 1); +// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: A a_9{0, 1}; +A a_10( 1, 0 ); +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: A a_10{1, 0}; +A a_11(A(3)); +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: A a_11{A(3)}; +A a_12 ( A(3) ); +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: A a_12 {A(3)}; + +struct Delegating { + Delegating() : Delegating(0) {} + // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] + // CHECK-FIXES: Delegating() : Delegating{0} {} + + Delegating(int) {} +}; + +int narrow_0 = 3.14; +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int narrow_0 {static_cast<int>(3.14)}; +int narrow_1=37.73; +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: Use uniform initializer instead of C-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int narrow_1{static_cast<int>(37.73)}; +int narrow_2(0.9); +// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int narrow_2{static_cast<int>(0.9)}; +int narrow_3 ( 5.666 ); +// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: Use uniform initializer instead of call-style initializer [modernize-use-uniform-initializer] +// CHECK-FIXES: int narrow_3 {static_cast<int>(5.666)}; + +template <class T> struct Vec { + T *begin(); + T *end(); +}; + +void for_each() { + Vec<int> v; + for (int& x : v) + {} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits