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.


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to