[clang-tools-extra] [clang-tidy] Add new check `modernize-use-designated-initializers` (PR #80541)
Danny Mösch via cfe-commits
cfe-commits at lists.llvm.org
Sat Feb 3 05:31:44 PST 2024
https://github.com/SimplyDanny updated https://github.com/llvm/llvm-project/pull/80541
>From a6f7d8f72ab4af680dc17004e9bccefbe268b712 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moesch at icloud.com>
Date: Sat, 3 Feb 2024 13:13:50 +0100
Subject: [PATCH 1/8] 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.moesch at icloud.com>
Date: Sat, 3 Feb 2024 13:34:58 +0100
Subject: [PATCH 2/8] 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.moesch at icloud.com>
Date: Sat, 3 Feb 2024 13:35:12 +0100
Subject: [PATCH 3/8] 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.moesch at icloud.com>
Date: Sat, 3 Feb 2024 13:36:10 +0100
Subject: [PATCH 4/8] 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.moesch at icloud.com>
Date: Sat, 3 Feb 2024 13:56:08 +0100
Subject: [PATCH 5/8] 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.moesch at icloud.com>
Date: Sat, 3 Feb 2024 14:06:17 +0100
Subject: [PATCH 6/8] 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.moesch at icloud.com>
Date: Sat, 3 Feb 2024 14:22:56 +0100
Subject: [PATCH 7/8] 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`.
>From 0654d19199210985bf7d4435598aeb66604fd76f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Danny=20M=C3=B6sch?= <danny.moesch at icloud.com>
Date: Sat, 3 Feb 2024 14:31:30 +0100
Subject: [PATCH 8/8] Fix typo
---
.../clang-tidy/checks/modernize/use-designated-initializers.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
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 1e182218dbd8e..27474921a53d5 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
@@ -38,7 +38,7 @@ declaration of ``S``.
Options
-------
-.. options:: IgnoreSingleElementAggregates
+.. option:: IgnoreSingleElementAggregates
The value `false` specifies that even initializers for aggregate types
with only a single element should be checked. The default value is `true`.
More information about the cfe-commits
mailing list