[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.
This commit is contained in:
Daniil Dudkin 2026-05-09 12:16:36 +03:00 committed by GitHub
parent 7c9f1d2128
commit d3a4bb081f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 30 additions and 0 deletions

View file

@ -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),

View file

@ -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:

View file

@ -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 @@ public:
// 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.