[clang-tools-extra] d3a4bb0 - [clang-tidy] Avoid `use-nodiscard` false positives for class templates (#196661)
via cfe-commits
cfe-commits at lists.llvm.org
Sat May 9 02:16:41 PDT 2026
Author: Daniil Dudkin
Date: 2026-05-09T12:16:36+03:00
New Revision: d3a4bb081f6c3d6b410af0639f7ad2bb652c1d03
URL: https://github.com/llvm/llvm-project/commit/d3a4bb081f6c3d6b410af0639f7ad2bb652c1d03
DIFF: https://github.com/llvm/llvm-project/commit/d3a4bb081f6c3d6b410af0639f7ad2bb652c1d03.diff
LOG: [clang-tidy] Avoid `use-nodiscard` false positives for class templates (#196661)
Do not suggest adding `[[nodiscard]]` to functions returning a class
template specialization whose primary template is already marked
`[[nodiscard]]`.
Class template specializations do not carry the `[[nodiscard]]`
attribute on their own declarations, so `modernize-use-nodiscard`
previously missed this case and emitted redundant diagnostics for return
types such as:
```cpp
template <class T>
struct [[nodiscard]] Result;
Result<int> f() const;
```
Fixes #163425.
Added:
Modified:
clang-tools-extra/clang-tidy/modernize/UseNodiscardCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/test/clang-tidy/checkers/modernize/use-nodiscard.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/modernize/UseNodiscardCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNodiscardCheck.cpp
index 4940b5590f803..caa3d8c00681e 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseNodiscardCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseNodiscardCheck.cpp
@@ -84,6 +84,9 @@ void UseNodiscardCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
void UseNodiscardCheck::registerMatchers(MatchFinder *Finder) {
auto FunctionObj =
cxxRecordDecl(hasAnyName("::std::function", "::boost::function"));
+ auto NoDiscardClassTemplateSpecialization =
+ classTemplateSpecializationDecl(hasSpecializedTemplate(classTemplateDecl(
+ has(cxxRecordDecl(hasAttr(attr::WarnUnusedResult))))));
// Find all non-void const methods which have not already been marked to
// warn on unused result.
@@ -93,6 +96,8 @@ void UseNodiscardCheck::registerMatchers(MatchFinder *Finder) {
unless(anyOf(
returns(voidType()),
returns(hasDeclaration(decl(hasAttr(attr::WarnUnusedResult)))),
+ returns(hasUnqualifiedDesugaredType(recordType(
+ hasDeclaration(NoDiscardClassTemplateSpecialization)))),
isNoReturn(), isOverloadedOperator(), isVariadic(),
hasTemplateReturnType(), hasClassMutableFields(),
isConversionOperator(), hasAttr(attr::WarnUnusedResult),
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index c464be5f6311a..783c919f8ce8e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -440,6 +440,11 @@ Changes in existing checks
private deleted functions, if they do not have a public overload or are a
special member function.
+- Improved :doc:`modernize-use-nodiscard
+ <clang-tidy/checks/modernize/use-nodiscard>` check by avoiding false
+ positives on functions returning specializations of class templates marked
+ ``[[nodiscard]]``.
+
- Improved :doc:`modernize-use-std-format
<clang-tidy/checks/modernize/use-std-format>` check:
diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nodiscard.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nodiscard.cpp
index 73ea4e46f76b6..e9097a7b19fdd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nodiscard.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-nodiscard.cpp
@@ -24,6 +24,12 @@ typedef const unsigned &my_unsigned_const_reference;
struct NO_DISCARD NoDiscardStruct{};
+template <typename T>
+struct NO_DISCARD NoDiscardTemplate {};
+
+using NoDiscardTemplateAlias = NoDiscardTemplate<int>;
+typedef NoDiscardTemplate<int> NoDiscardTemplateTypedef;
+
class Foo {
public:
using size_type = unsigned;
@@ -164,6 +170,20 @@ class Foo {
// Do not add ``[[nodiscard]]`` to functions returning types marked [[nodiscard]].
NoDiscardStruct f50() const;
+
+ // Do not add ``[[nodiscard]]`` to functions returning class template
+ // specializations whose primary template is marked [[nodiscard]].
+ NoDiscardTemplate<int> f51() const;
+
+ NoDiscardTemplateAlias f52() const;
+
+ NoDiscardTemplateTypedef f53() const;
+
+ const NoDiscardTemplate<int> f54() const;
+
+ const NoDiscardTemplate<int> &f55() const;
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: function 'f55' should be marked NO_DISCARD [modernize-use-nodiscard]
+ // CHECK-FIXES: NO_DISCARD const NoDiscardTemplate<int> &f55() const;
};
// Do not add ``[[nodiscard]]`` to Lambda.
More information about the cfe-commits
mailing list