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 <[email protected]> Date: Sun, 8 Feb 2026 16:23:22 +0300 Subject: [PATCH] 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); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
