[clang-tools-extra] [clang-tidy] comment braced-init list arguments (PR #180408)
Daniil Dudkin via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 15 07:18:20 PST 2026
https://github.com/unterumarmung updated https://github.com/llvm/llvm-project/pull/180408
>From 312ae7af727d85acb2c9153bc4d36635a7bb5a5f Mon Sep 17 00:00:00 2001
From: Daniil Dudkin <unterumarmung at yandex.ru>
Date: Sun, 8 Feb 2026 16:23:22 +0300
Subject: [PATCH 1/2] clang-tidy: comment braced-init list arguments
Handle braced-init list arguments in bugprone-argument-comment and\nadd coverage for initializer_list and designated initializers.
clang-tidy: gate braced-init argument comments behind options
clang-tidy: split argument-comment init-list tests
---
.../bugprone/ArgumentCommentCheck.cpp | 57 ++++++++-
.../bugprone/ArgumentCommentCheck.h | 2 +
clang-tools-extra/docs/ReleaseNotes.rst | 7 +-
.../checks/bugprone/argument-comment.rst | 44 +++++++
.../bugprone/argument-comment-init-list.cpp | 108 ++++++++++++++++++
.../bugprone/argument-comment-literals.cpp | 3 +-
6 files changed, 214 insertions(+), 7 deletions(-)
create mode 100644 clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-init-list.cpp
diff --git a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp
index eb9b710b28549..3e972d6f91fc9 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp
@@ -43,6 +43,9 @@ ArgumentCommentCheck::ArgumentCommentCheck(StringRef Name,
CommentUserDefinedLiterals(
Options.get("CommentUserDefinedLiterals", false)),
CommentCharacterLiterals(Options.get("CommentCharacterLiterals", false)),
+ CommentAnonymousInitLists(
+ Options.get("CommentAnonymousInitLists", false)),
+ CommentTypedInitLists(Options.get("CommentTypedInitLists", false)),
CommentNullPtrs(Options.get("CommentNullPtrs", false)),
IdentRE("^(/\\* *)([_A-Za-z][_A-Za-z0-9]*)( *= *\\*/)$") {}
@@ -55,6 +58,8 @@ void ArgumentCommentCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "CommentStringLiterals", CommentStringLiterals);
Options.store(Opts, "CommentUserDefinedLiterals", CommentUserDefinedLiterals);
Options.store(Opts, "CommentCharacterLiterals", CommentCharacterLiterals);
+ Options.store(Opts, "CommentAnonymousInitLists", CommentAnonymousInitLists);
+ Options.store(Opts, "CommentTypedInitLists", CommentTypedInitLists);
Options.store(Opts, "CommentNullPtrs", CommentNullPtrs);
}
@@ -199,14 +204,60 @@ static const FunctionDecl *resolveMocks(const FunctionDecl *Func) {
return Func;
}
+enum class InitListKind {
+ None,
+ Anonymous,
+ Typed,
+};
+
+static InitListKind getInitListKind(const Expr *Arg) {
+ Arg = Arg->IgnoreImplicit();
+
+ if (const auto *StdInit = dyn_cast<CXXStdInitializerListExpr>(Arg))
+ return getInitListKind(StdInit->getSubExpr());
+
+ if (isa<InitListExpr>(Arg))
+ return InitListKind::Anonymous;
+
+ if (const auto *Ctor = dyn_cast<CXXConstructExpr>(Arg)) {
+ if (!Ctor->isListInitialization())
+ return InitListKind::None;
+ // CXXTemporaryObjectExpr corresponds to explicit Type{...} syntax.
+ if (isa<CXXTemporaryObjectExpr>(Ctor))
+ return InitListKind::Typed;
+ // Other list-initialized constructions (for example '{}') have no
+ // explicit type at the call site.
+ return InitListKind::Anonymous;
+ }
+
+ if (const auto *FuncCast = dyn_cast<CXXFunctionalCastExpr>(Arg)) {
+ if (FuncCast->isListInitialization())
+ return InitListKind::Typed;
+ }
+
+ return InitListKind::None;
+}
+
// Given the argument type and the options determine if we should
// be adding an argument comment.
bool ArgumentCommentCheck::shouldAddComment(const Expr *Arg) const {
- Arg = Arg->IgnoreImpCasts();
- if (isa<UnaryOperator>(Arg))
- Arg = cast<UnaryOperator>(Arg)->getSubExpr();
+ // Strip implicit wrappers so brace-init arguments bound to references still
+ // look like list-initialization at this point.
+ Arg = Arg->IgnoreImplicit();
+ if (const auto *UO = dyn_cast<UnaryOperator>(Arg))
+ Arg = UO->getSubExpr()->IgnoreImplicit();
if (Arg->getExprLoc().isMacroID())
return false;
+
+ switch (getInitListKind(Arg)) {
+ case InitListKind::Anonymous:
+ return CommentAnonymousInitLists;
+ case InitListKind::Typed:
+ return CommentTypedInitLists;
+ case InitListKind::None:
+ break;
+ }
+
return (CommentBoolLiterals && isa<CXXBoolLiteralExpr>(Arg)) ||
(CommentIntegerLiterals && isa<IntegerLiteral>(Arg)) ||
(CommentFloatLiterals && isa<FloatingLiteral>(Arg)) ||
diff --git a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h
index 30fa32fad72e7..60a1338233f66 100644
--- a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h
+++ b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.h
@@ -46,6 +46,8 @@ class ArgumentCommentCheck : public ClangTidyCheck {
const unsigned CommentStringLiterals : 1;
const unsigned CommentUserDefinedLiterals : 1;
const unsigned CommentCharacterLiterals : 1;
+ const unsigned CommentAnonymousInitLists : 1;
+ const unsigned CommentTypedInitLists : 1;
const unsigned CommentNullPtrs : 1;
llvm::Regex IdentRE;
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 5c0060877a67f..3bd3ec498dcd7 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -146,8 +146,11 @@ Changes in existing checks
^^^^^^^^^^^^^^^^^^^^^^^^^^
- Improved :doc:`bugprone-argument-comment
- <clang-tidy/checks/bugprone/argument-comment>` to also check for C++11
- inherited constructors.
+ <clang-tidy/checks/bugprone/argument-comment>`:
+ - Also checks for C++11 inherited constructors.
+ - Adds ``CommentAnonymousInitLists`` and ``CommentTypedInitLists`` options
+ to comment braced-init list arguments (for example, ``{}`` and
+ ``Type{}``).
- Improved :doc:`bugprone-bad-signal-to-kill-thread
<clang-tidy/checks/bugprone/bad-signal-to-kill-thread>` check by fixing false
diff --git a/clang-tools-extra/docs/clang-tidy/checks/bugprone/argument-comment.rst b/clang-tools-extra/docs/clang-tidy/checks/bugprone/argument-comment.rst
index 8770d7224137a..dc028cde2fcc4 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/bugprone/argument-comment.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/bugprone/argument-comment.rst
@@ -146,6 +146,50 @@ After:
foo(/*Character=*/'A');
+.. option:: CommentAnonymousInitLists
+
+ When `true`, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before anonymous braced-init list arguments
+ such as ``{}`` and ``{1, 2, 3}``. Default is `false`.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(const std::vector<int> &Dims);
+
+ foo({});
+
+After:
+
+.. code-block:: c++
+
+ void foo(const std::vector<int> &Dims);
+
+ foo(/*Dims=*/{});
+
+.. option:: CommentTypedInitLists
+
+ When `true`, the check will add argument comments in the format
+ ``/*ParameterName=*/`` right before typed braced-init list arguments such
+ as ``Type{}``. Default is `false`.
+
+Before:
+
+.. code-block:: c++
+
+ void foo(const std::vector<int> &Dims);
+
+ foo(std::vector<int>{});
+
+After:
+
+.. code-block:: c++
+
+ void foo(const std::vector<int> &Dims);
+
+ foo(/*Dims=*/std::vector<int>{});
+
.. option:: CommentUserDefinedLiterals
When `true`, the check will add argument comments in the format
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-init-list.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-init-list.cpp
new file mode 100644
index 0000000000000..d98695f81fdd0
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-init-list.cpp
@@ -0,0 +1,108 @@
+// RUN: %check_clang_tidy -check-suffix=OFF -std=c++11,c++14,c++17 %s bugprone-argument-comment %t
+// RUN: %check_clang_tidy -check-suffix=ANON -std=c++11,c++14,c++17 %s bugprone-argument-comment %t -- \
+// RUN: -config="{CheckOptions: { \
+// RUN: bugprone-argument-comment.CommentAnonymousInitLists: true}}" --
+// RUN: %check_clang_tidy -check-suffix=TYPED -std=c++11,c++14,c++17 %s bugprone-argument-comment %t -- \
+// RUN: -config="{CheckOptions: { \
+// RUN: bugprone-argument-comment.CommentTypedInitLists: true}}" --
+// RUN: %check_clang_tidy -check-suffix=BOTH -std=c++11,c++14,c++17 %s bugprone-argument-comment %t -- \
+// RUN: -config="{CheckOptions: { \
+// RUN: bugprone-argument-comment.CommentAnonymousInitLists: true, \
+// RUN: bugprone-argument-comment.CommentTypedInitLists: true}}" --
+// RUN: %check_clang_tidy -check-suffixes=BOTH,BOTH-CXX20 -std=c++20-or-later %s bugprone-argument-comment %t -- \
+// RUN: -config="{CheckOptions: { \
+// RUN: bugprone-argument-comment.CommentAnonymousInitLists: true, \
+// RUN: bugprone-argument-comment.CommentTypedInitLists: true}}" --
+
+namespace std {
+using size_t = decltype(sizeof(0));
+
+template <typename T>
+class vector {
+public:
+ vector();
+};
+
+template <typename T>
+class initializer_list {
+ const T *Begin;
+ const T *End;
+
+public:
+ initializer_list() : Begin(nullptr), End(nullptr) {}
+ const T *begin() const { return Begin; }
+ const T *end() const { return End; }
+ size_t size() const { return static_cast<size_t>(End - Begin); }
+};
+} // namespace std
+
+namespace GH171842 {
+
+struct T {
+ int value;
+};
+
+struct Agg {
+ int x;
+ int y;
+};
+
+void foo(T some_arg, const std::vector<int> &dims);
+void foo_init_list(T some_arg, std::initializer_list<int> dims);
+void foo_designated(T some_arg, const Agg &dims);
+
+void test_braced_init_list() {
+ T some_arg{0};
+
+ // Mismatched explicit argument comments are validated independently of the
+ // init-list literal comment options.
+ foo(some_arg, /*dim=*/{});
+ // CHECK-MESSAGES-OFF: warning: argument name 'dim' in comment does not match parameter name 'dims'
+ // CHECK-FIXES-OFF: foo(some_arg, /*dims=*/{});
+ // CHECK-MESSAGES-ANON: warning: argument name 'dim' in comment does not match parameter name 'dims'
+ // CHECK-FIXES-ANON: foo(some_arg, /*dims=*/{});
+ // CHECK-MESSAGES-TYPED: warning: argument name 'dim' in comment does not match parameter name 'dims'
+ // CHECK-FIXES-TYPED: foo(some_arg, /*dims=*/{});
+ // CHECK-MESSAGES-BOTH: warning: argument name 'dim' in comment does not match parameter name 'dims'
+ // CHECK-FIXES-BOTH: foo(some_arg, /*dims=*/{});
+
+ foo(some_arg, {});
+ // CHECK-FIXES-OFF: foo(some_arg, {});
+ // CHECK-MESSAGES-ANON: [[@LINE-2]]:17: warning: argument comment missing for literal argument 'dims' [bugprone-argument-comment]
+ // CHECK-FIXES-ANON: foo(some_arg, /*dims=*/{});
+ // CHECK-FIXES-TYPED: foo(some_arg, {});
+ // CHECK-MESSAGES-BOTH: [[@LINE-5]]:17: warning: argument comment missing for literal argument 'dims' [bugprone-argument-comment]
+ // CHECK-FIXES-BOTH: foo(some_arg, /*dims=*/{});
+
+ foo(some_arg, std::vector<int>{});
+ // CHECK-FIXES-OFF: foo(some_arg, std::vector<int>{});
+ // CHECK-FIXES-ANON: foo(some_arg, std::vector<int>{});
+ // CHECK-MESSAGES-TYPED: [[@LINE-3]]:17: warning: argument comment missing for literal argument 'dims' [bugprone-argument-comment]
+ // CHECK-FIXES-TYPED: foo(some_arg, /*dims=*/std::vector<int>{});
+ // CHECK-MESSAGES-BOTH: [[@LINE-5]]:17: warning: argument comment missing for literal argument 'dims' [bugprone-argument-comment]
+ // CHECK-FIXES-BOTH: foo(some_arg, /*dims=*/std::vector<int>{});
+}
+
+void test_initializer_list() {
+ T some_arg{0};
+
+ foo_init_list(some_arg, {1, 2, 3});
+ // CHECK-FIXES-OFF: foo_init_list(some_arg, {1, 2, 3});
+ // CHECK-MESSAGES-ANON: [[@LINE-2]]:27: warning: argument comment missing for literal argument 'dims' [bugprone-argument-comment]
+ // CHECK-FIXES-ANON: foo_init_list(some_arg, /*dims=*/{1, 2, 3});
+ // CHECK-FIXES-TYPED: foo_init_list(some_arg, {1, 2, 3});
+ // CHECK-MESSAGES-BOTH: [[@LINE-5]]:27: warning: argument comment missing for literal argument 'dims' [bugprone-argument-comment]
+ // CHECK-FIXES-BOTH: foo_init_list(some_arg, /*dims=*/{1, 2, 3});
+}
+
+#if __cplusplus >= 202002L
+void test_designated_init() {
+ T some_arg{0};
+
+ foo_designated(some_arg, Agg{.x = 1});
+ // CHECK-MESSAGES-BOTH-CXX20: [[@LINE-1]]:28: warning: argument comment missing for literal argument 'dims' [bugprone-argument-comment]
+ // CHECK-FIXES-BOTH-CXX20: foo_designated(some_arg, /*dims=*/Agg{.x = 1});
+}
+#endif
+
+} // namespace GH171842
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-literals.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-literals.cpp
index f03488a14d9f5..870c198f8058f 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-literals.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/argument-comment-literals.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s bugprone-argument-comment %t -- \
+// RUN: %check_clang_tidy -std=c++11,c++14,c++17 %s bugprone-argument-comment %t -- \
// RUN: -config="{CheckOptions: { \
// RUN: bugprone-argument-comment.CommentBoolLiterals: true, \
// RUN: bugprone-argument-comment.CommentIntegerLiterals: true, \
@@ -7,7 +7,6 @@
// RUN: bugprone-argument-comment.CommentStringLiterals: true, \
// RUN: bugprone-argument-comment.CommentNullPtrs: true, \
// RUN: bugprone-argument-comment.CommentCharacterLiterals: true}}" --
-
struct A {
void foo(bool abc);
void foo(bool abc, bool cde);
>From 042f2101dddcc98b35b37e1c3b99169d09a43725 Mon Sep 17 00:00:00 2001
From: Daniil Dudkin <unterumarmung at yandex.ru>
Date: Sun, 15 Feb 2026 18:18:13 +0300
Subject: [PATCH 2/2] Apply suggestions from code review
Co-authored-by: EugeneZelenko <eugene.zelenko at gmail.com>
---
clang-tools-extra/docs/ReleaseNotes.rst | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 3bd3ec498dcd7..dbd70a523540a 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -147,8 +147,10 @@ Changes in existing checks
- Improved :doc:`bugprone-argument-comment
<clang-tidy/checks/bugprone/argument-comment>`:
+
- Also checks for C++11 inherited constructors.
- - Adds ``CommentAnonymousInitLists`` and ``CommentTypedInitLists`` options
+
+ - Adds `CommentAnonymousInitLists` and `CommentTypedInitLists` options
to comment braced-init list arguments (for example, ``{}`` and
``Type{}``).
More information about the cfe-commits
mailing list