https://github.com/SimplyDanny created https://github.com/llvm/llvm-project/pull/80541
Resolves #77618. From a6f7d8f72ab4af680dc17004e9bccefbe268b712 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moe...@icloud.com> Date: Sat, 3 Feb 2024 13:13:50 +0100 Subject: [PATCH 1/7] Trigger on variable declarations --- .../clang-tidy/modernize/CMakeLists.txt | 1 + .../modernize/ModernizeTidyModule.cpp | 3 + .../UseDesignatedInitializersCheck.cpp | 58 +++++++++++++++++++ .../UseDesignatedInitializersCheck.h | 33 +++++++++++ clang-tools-extra/docs/ReleaseNotes.rst | 5 ++ .../docs/clang-tidy/checks/list.rst | 1 + .../modernize/use-designated-initializers.rst | 6 ++ .../modernize/use-designated-initializers.cpp | 32 ++++++++++ 8 files changed, 139 insertions(+) create mode 100644 clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index 28ca52f46943a..6852db6c2ee31 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -31,6 +31,7 @@ add_clang_library(clangTidyModernizeModule UseBoolLiteralsCheck.cpp UseConstraintsCheck.cpp UseDefaultMemberInitCheck.cpp + UseDesignatedInitializersCheck.cpp UseEmplaceCheck.cpp UseEqualsDefaultCheck.cpp UseEqualsDeleteCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index 654f4bd0c6ba4..e96cf274f58cf 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -32,6 +32,7 @@ #include "UseBoolLiteralsCheck.h" #include "UseConstraintsCheck.h" #include "UseDefaultMemberInitCheck.h" +#include "UseDesignatedInitializersCheck.h" #include "UseEmplaceCheck.h" #include "UseEqualsDefaultCheck.h" #include "UseEqualsDeleteCheck.h" @@ -68,6 +69,8 @@ class ModernizeModule : public ClangTidyModule { CheckFactories.registerCheck<MakeSharedCheck>("modernize-make-shared"); CheckFactories.registerCheck<MakeUniqueCheck>("modernize-make-unique"); CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value"); + CheckFactories.registerCheck<UseDesignatedInitializersCheck>( + "modernize-use-designated-initializers"); CheckFactories.registerCheck<UseStartsEndsWithCheck>( "modernize-use-starts-ends-with"); CheckFactories.registerCheck<UseStdNumbersCheck>( diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp new file mode 100644 index 0000000000000..06f0bb0dc06ea --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp @@ -0,0 +1,58 @@ +//===--- UseDesignatedInitializersCheck.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 "UseDesignatedInitializersCheck.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" +#include <algorithm> +#include <iterator> +#include <vector> + +using namespace clang::ast_matchers; + +namespace clang::tidy::modernize { + +static std::vector<Stmt *> +getAllUndesignatedInits(const InitListExpr *SyntacticInitList) { + std::vector<Stmt *> Result; + std::copy_if(SyntacticInitList->begin(), SyntacticInitList->end(), + std::back_inserter(Result), + [](auto S) { return !isa<DesignatedInitExpr>(S); }); + return Result; +} + +void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(varDecl(allOf(has(initListExpr().bind("init")), + hasType(recordDecl().bind("type")))), + this); +} + +void UseDesignatedInitializersCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *InitList = Result.Nodes.getNodeAs<InitListExpr>("init"); + const auto *Type = Result.Nodes.getNodeAs<CXXRecordDecl>("type"); + if (!Type || !InitList || !Type->isAggregate()) + return; + if (const auto *SyntacticInitList = InitList->getSyntacticForm()) { + const auto UndesignatedParts = getAllUndesignatedInits(SyntacticInitList); + if (UndesignatedParts.empty()) + return; + if (UndesignatedParts.size() == SyntacticInitList->getNumInits()) { + diag(InitList->getLBraceLoc(), "use designated initializer list"); + return; + } + for (const auto *InitExpr : UndesignatedParts) { + diag(InitExpr->getBeginLoc(), "use designated init expression"); + } + } +} + +} // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h new file mode 100644 index 0000000000000..aeaa3f19deb7e --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h @@ -0,0 +1,33 @@ +//===--- UseDesignatedInitializersCheck.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_USEDESIGNATEDINITIALIZERSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEDESIGNATEDINITIALIZERSCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::modernize { + +/// FIXME: Write a short description. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-designated-initializers.html +class UseDesignatedInitializersCheck : public ClangTidyCheck { +public: + UseDesignatedInitializersCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + std::optional<TraversalKind> getCheckTraversalKind() const override { + return TK_IgnoreUnlessSpelledInSource; + } +}; + +} // namespace clang::tidy::modernize + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USEDESIGNATEDINITIALIZERSCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 9e819ea34c397..a9e4305e7ca5a 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -100,6 +100,11 @@ Improvements to clang-tidy New checks ^^^^^^^^^^ +- New :doc:`modernize-use-designated-initializers + <clang-tidy/checks/modernize/use-designated-initializers>` check. + + FIXME: add release notes. + 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 f40192ed9dea2..5d3b99e0996c2 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -287,6 +287,7 @@ Clang-Tidy Checks :doc:`modernize-use-bool-literals <modernize/use-bool-literals>`, "Yes" :doc:`modernize-use-constraints <modernize/use-constraints>`, "Yes" :doc:`modernize-use-default-member-init <modernize/use-default-member-init>`, "Yes" + :doc:`modernize-use-designated-initializers <modernize/use-designated-initializers>`, "Yes" :doc:`modernize-use-emplace <modernize/use-emplace>`, "Yes" :doc:`modernize-use-equals-default <modernize/use-equals-default>`, "Yes" :doc:`modernize-use-equals-delete <modernize/use-equals-delete>`, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst new file mode 100644 index 0000000000000..e0487f9b0e843 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst @@ -0,0 +1,6 @@ +.. title:: clang-tidy - modernize-use-designated-initializers + +modernize-use-designated-initializers +===================================== + +FIXME: Describe what patterns does the check detect and why. Give examples. diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp new file mode 100644 index 0000000000000..c945454201ee1 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp @@ -0,0 +1,32 @@ +// RUN: %check_clang_tidy %s modernize-use-designated-initializers %t + +struct S1 {}; + +S1 s11{}; +S1 s12 = {}; +S1 s13(); +S1 s14; + +struct S2 { int i, j; }; + +S2 s21{.i=1, .j =2}; + +S2 s22 = {1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list [modernize-use-designated-initializers] + +S2 s23{1}; +// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use designated initializer list [modernize-use-designated-initializers] + +S2 s24{.i = 1}; + +S2 s25 = {.i=1, 2}; +// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use designated init expression [modernize-use-designated-initializers] + +struct S3 { + S2 s2; + double d; +}; + +S3 s31 = {.s2 = 1, 2, 3.1}; +// CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use designated init expression [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use designated init expression [modernize-use-designated-initializers] From 17301b2e09157b6b571c744b0a28a740d8f51c26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moe...@icloud.com> Date: Sat, 3 Feb 2024 13:34:58 +0100 Subject: [PATCH 2/7] Support nested initializer lists --- .../modernize/UseDesignatedInitializersCheck.cpp | 5 ++--- .../modernize/use-designated-initializers.cpp | 12 ++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp index 06f0bb0dc06ea..e0400db473db2 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp @@ -30,9 +30,8 @@ getAllUndesignatedInits(const InitListExpr *SyntacticInitList) { } void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) { - Finder->addMatcher(varDecl(allOf(has(initListExpr().bind("init")), - hasType(recordDecl().bind("type")))), - this); + Finder->addMatcher( + initListExpr(hasType(recordDecl().bind("type"))).bind("init"), this); } void UseDesignatedInitializersCheck::check( diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp index c945454201ee1..a5eeb5553a909 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp @@ -30,3 +30,15 @@ struct S3 { S3 s31 = {.s2 = 1, 2, 3.1}; // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use designated init expression [modernize-use-designated-initializers] // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: use designated init expression [modernize-use-designated-initializers] + +S3 s32 = {{.i = 1, 2}}; +// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use designated initializer list [modernize-use-designated-initializers] +// CHECK-MESSAGES: :[[@LINE-2]]:20: warning: use designated init expression [modernize-use-designated-initializers] + +struct S4 { + double d; + private: static int i; +}; + +S4 s41 {2.2}; +// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use designated initializer list [modernize-use-designated-initializers] From 301893ebc4366be0598a57fbe31d20dfac9ba200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moe...@icloud.com> Date: Sat, 3 Feb 2024 13:35:12 +0100 Subject: [PATCH 3/7] Rename --- .../modernize/UseDesignatedInitializersCheck.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp index e0400db473db2..7cf6dcb21ac1b 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp @@ -21,7 +21,7 @@ using namespace clang::ast_matchers; namespace clang::tidy::modernize { static std::vector<Stmt *> -getAllUndesignatedInits(const InitListExpr *SyntacticInitList) { +getUndesignatedComponents(const InitListExpr *SyntacticInitList) { std::vector<Stmt *> Result; std::copy_if(SyntacticInitList->begin(), SyntacticInitList->end(), std::back_inserter(Result), @@ -41,14 +41,15 @@ void UseDesignatedInitializersCheck::check( if (!Type || !InitList || !Type->isAggregate()) return; if (const auto *SyntacticInitList = InitList->getSyntacticForm()) { - const auto UndesignatedParts = getAllUndesignatedInits(SyntacticInitList); - if (UndesignatedParts.empty()) + const auto UndesignatedComponents = + getUndesignatedComponents(SyntacticInitList); + if (UndesignatedComponents.empty()) return; - if (UndesignatedParts.size() == SyntacticInitList->getNumInits()) { + if (UndesignatedComponents.size() == SyntacticInitList->getNumInits()) { diag(InitList->getLBraceLoc(), "use designated initializer list"); return; } - for (const auto *InitExpr : UndesignatedParts) { + for (const auto *InitExpr : UndesignatedComponents) { diag(InitExpr->getBeginLoc(), "use designated init expression"); } } From b71c6fab7c24859df17d051eb0b8746aa089e574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moe...@icloud.com> Date: Sat, 3 Feb 2024 13:36:10 +0100 Subject: [PATCH 4/7] Enable for C++20 only --- .../clang-tidy/modernize/UseDesignatedInitializersCheck.h | 3 +++ .../checkers/modernize/use-designated-initializers.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h index aeaa3f19deb7e..12a9850ada6a1 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h @@ -26,6 +26,9 @@ class UseDesignatedInitializersCheck : public ClangTidyCheck { std::optional<TraversalKind> getCheckTraversalKind() const override { return TK_IgnoreUnlessSpelledInSource; } + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus20; + } }; } // namespace clang::tidy::modernize diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp index a5eeb5553a909..7e41943e88406 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp @@ -1,4 +1,4 @@ -// RUN: %check_clang_tidy %s modernize-use-designated-initializers %t +// RUN: %check_clang_tidy -std=c++20 %s modernize-use-designated-initializers %t struct S1 {}; From 444b58996764e2585369a3c3112a42fa43365a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moe...@icloud.com> Date: Sat, 3 Feb 2024 13:56:08 +0100 Subject: [PATCH 5/7] Add option to ignore aggregates with single elements --- .../UseDesignatedInitializersCheck.cpp | 19 +++++++++++++++++++ .../UseDesignatedInitializersCheck.h | 9 +++++++-- .../modernize/use-designated-initializers.cpp | 5 ++++- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp index 7cf6dcb21ac1b..d269cef13e6aa 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp @@ -20,6 +20,10 @@ using namespace clang::ast_matchers; namespace clang::tidy::modernize { +static constexpr auto IgnoreSingleElementAggregatesName = + "IgnoreSingleElementAggregates"; +static constexpr auto IgnoreSingleElementAggregatesDefault = true; + static std::vector<Stmt *> getUndesignatedComponents(const InitListExpr *SyntacticInitList) { std::vector<Stmt *> Result; @@ -29,6 +33,13 @@ getUndesignatedComponents(const InitListExpr *SyntacticInitList) { return Result; } +UseDesignatedInitializersCheck::UseDesignatedInitializersCheck( + StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + IgnoreSingleElementAggregates( + Options.getLocalOrGlobal(IgnoreSingleElementAggregatesName, + IgnoreSingleElementAggregatesDefault)) {} + void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( initListExpr(hasType(recordDecl().bind("type"))).bind("init"), this); @@ -40,6 +51,8 @@ void UseDesignatedInitializersCheck::check( const auto *Type = Result.Nodes.getNodeAs<CXXRecordDecl>("type"); if (!Type || !InitList || !Type->isAggregate()) return; + if (IgnoreSingleElementAggregates && InitList->getNumInits() == 1) + return; if (const auto *SyntacticInitList = InitList->getSyntacticForm()) { const auto UndesignatedComponents = getUndesignatedComponents(SyntacticInitList); @@ -55,4 +68,10 @@ void UseDesignatedInitializersCheck::check( } } +void UseDesignatedInitializersCheck::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, IgnoreSingleElementAggregatesName, + IgnoreSingleElementAggregates); +} + } // namespace clang::tidy::modernize diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h index 12a9850ada6a1..8a60fd7b31c5a 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h @@ -19,16 +19,21 @@ namespace clang::tidy::modernize { /// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-designated-initializers.html class UseDesignatedInitializersCheck : public ClangTidyCheck { public: - UseDesignatedInitializersCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + UseDesignatedInitializersCheck(StringRef Name, ClangTidyContext *Context); void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: std::optional<TraversalKind> getCheckTraversalKind() const override { return TK_IgnoreUnlessSpelledInSource; } bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus20; } + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + +private: + bool IgnoreSingleElementAggregates; }; } // namespace clang::tidy::modernize diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp index 7e41943e88406..350ee03d581ae 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp @@ -1,4 +1,7 @@ // RUN: %check_clang_tidy -std=c++20 %s modernize-use-designated-initializers %t +// RUN: %check_clang_tidy -check-suffixes=,SINGLE-ELEMENT -std=c++20 %s modernize-use-designated-initializers %t \ +// RUN: -- -config="{CheckOptions: [{key: modernize-use-designated-initializers.IgnoreSingleElementAggregates, value: false}]}" \ +// RUN: -- struct S1 {}; @@ -41,4 +44,4 @@ struct S4 { }; S4 s41 {2.2}; -// CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use designated initializer list [modernize-use-designated-initializers] +// CHECK-MESSAGES-SINGLE-ELEMENT: :[[@LINE-1]]:8: warning: use designated initializer list [modernize-use-designated-initializers] From 69bad8a270b266271cb274d04794312054aca90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moe...@icloud.com> Date: Sat, 3 Feb 2024 14:06:17 +0100 Subject: [PATCH 6/7] Test class --- .../checkers/modernize/use-designated-initializers.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp index 350ee03d581ae..d932e2d5e4863 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-designated-initializers.cpp @@ -25,7 +25,8 @@ S2 s24{.i = 1}; S2 s25 = {.i=1, 2}; // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use designated init expression [modernize-use-designated-initializers] -struct S3 { +class S3 { + public: S2 s2; double d; }; From 06091a0112d994c3618243dd13ca2d1581c352dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moe...@icloud.com> Date: Sat, 3 Feb 2024 14:22:56 +0100 Subject: [PATCH 7/7] Add documentation and release notes --- .../UseDesignatedInitializersCheck.h | 3 +- clang-tools-extra/docs/ReleaseNotes.rst | 3 +- .../modernize/use-designated-initializers.rst | 40 ++++++++++++++++++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h index 8a60fd7b31c5a..34290aba06fab 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h +++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.h @@ -13,7 +13,8 @@ namespace clang::tidy::modernize { -/// FIXME: Write a short description. +/// Triggers on initializer lists for aggregate type that could be +/// written as designated initializers instead. /// /// For the user-facing documentation see: /// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-designated-initializers.html diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index a9e4305e7ca5a..ce86f2ea455ff 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -103,7 +103,8 @@ New checks - New :doc:`modernize-use-designated-initializers <clang-tidy/checks/modernize/use-designated-initializers>` check. - FIXME: add release notes. + Triggers on initializer lists for aggregate type that could be + written as designated initializers instead. New check aliases ^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst index e0487f9b0e843..1e182218dbd8e 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/modernize/use-designated-initializers.rst @@ -3,4 +3,42 @@ modernize-use-designated-initializers ===================================== -FIXME: Describe what patterns does the check detect and why. Give examples. +Triggers on initializer lists for aggregate type that could be written as +designated initializers instead. + +With plain initializer lists, it is very easy to introduce bugs when adding +new fields in the middle of a struct or class type. The same confusion might +arise when changing the order of fields. + +C++ 20 supports the designated initializer syntax for aggregate types. +By applying it, we can always be sure that aggregates are constructed correctly, +because the every variable being initialized is referenced by name. + +Example: + +.. code-block:: + + struct S { int i, j; }; + +is an aggregate type that should be initialized as + +.. code-block:: + + S s{.i = 1, .j = 2}; + +instead of + +.. code-block:: + + S s{1, 2}; + +which could easily become an issue when ``i`` and ``j`` are swapped in the +declaration of ``S``. + +Options +------- + +.. options:: IgnoreSingleElementAggregates + + The value `false` specifies that even initializers for aggregate types + with only a single element should be checked. The default value is `true`. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits