https://github.com/nickdesaulniers updated 
https://github.com/llvm/llvm-project/pull/237374

>From a9c8e3620724100d70e97023ad2e342c106dd504 Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <[email protected]>
Date: Mon, 26 Oct 2026 13:12:45 -0700
Subject: [PATCH 1/2] [clang][Sema] fix -Wunused-private-field false-positive
 when use is templated

Don't warn when the use is in a templated function.

Fixes: #237370
Assisted-by: Gemini
---
 clang/lib/Sema/SemaDeclCXX.cpp                | 17 ++++++--------
 .../SemaCXX/warn-unused-private-field.cpp     | 22 +++++++++++++++++++
 2 files changed, 29 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 0fe0daa71c1bcf..90f6f54a41fb5c 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -3494,17 +3494,14 @@ inline static bool HasAttribute(const QualType &T) {
 }
 
 static bool IsUnusedPrivateField(const FieldDecl *FD) {
-  if (FD->getAccess() == AS_private && FD->getDeclName()) {
-    QualType FieldType = FD->getType();
-    if (HasAttribute<WarnUnusedAttr>(FieldType))
-      return true;
+  if (FD->isImplicit() || !FD->getDeclName() || FD->getAccess() != AS_private 
||
+      FD->hasAttr<UnusedAttr>() || FD->getParent()->isDependentContext())
+    return false;
 
-    return !FD->isImplicit() && !FD->hasAttr<UnusedAttr>() &&
-           !FD->getParent()->isDependentContext() &&
-           !HasAttribute<UnusedAttr>(FieldType) &&
-           !InitializationHasSideEffects(*FD);
-  }
-  return false;
+  QualType FieldType = FD->getType();
+  return !HasAttribute<UnusedAttr>(FieldType) &&
+         (HasAttribute<WarnUnusedAttr>(FieldType) ||
+          !InitializationHasSideEffects(*FD));
 }
 
 NamedDecl *
diff --git a/clang/test/SemaCXX/warn-unused-private-field.cpp 
b/clang/test/SemaCXX/warn-unused-private-field.cpp
index 0bcca6b82227f9..e8e6130801d560 100644
--- a/clang/test/SemaCXX/warn-unused-private-field.cpp
+++ b/clang/test/SemaCXX/warn-unused-private-field.cpp
@@ -354,3 +354,25 @@ class C {
   T t2;            // ok
 };
 }
+
+namespace warn_unused_template {
+struct [[gnu::warn_unused]] WarnUnusedType {};
+
+template <typename T>
+struct Outer {
+  class Inner {
+    friend struct Outer<T>;
+    WarnUnusedType field_;
+  };
+
+  WarnUnusedType use(Inner &i) {
+    return i.field_;
+  }
+};
+
+WarnUnusedType test() {
+  Outer<int> o;
+  Outer<int>::Inner i;
+  return o.use(i);
+}
+} // namespace warn_unused_template

>From fac498d92ad9a132d47dac6d75bd0204aef96e0b Mon Sep 17 00:00:00 2001
From: Nick Desaulniers <[email protected]>
Date: Mon, 2 Nov 2026 14:52:47 -0800
Subject: [PATCH 2/2] [clang][Sema] track instantiated fields for
 -Wunused-private-field

Insert instantiated fields into UnusedPrivateFields during template 
instantiation so unused private fields in instantiated templates are still 
diagnosed.

Assisted-by: Gemini
---
 clang/include/clang/Sema/SemaInternal.h          |  2 ++
 clang/lib/Sema/SemaDeclCXX.cpp                   |  2 +-
 clang/lib/Sema/SemaTemplateInstantiateDecl.cpp   |  5 +++++
 clang/test/SemaCXX/uninitialized.cpp             |  2 +-
 clang/test/SemaCXX/warn-unused-private-field.cpp | 14 +++++++++++++-
 5 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/clang/include/clang/Sema/SemaInternal.h 
b/clang/include/clang/Sema/SemaInternal.h
index 8f6041b5f00e47..5b560c378af473 100644
--- a/clang/include/clang/Sema/SemaInternal.h
+++ b/clang/include/clang/Sema/SemaInternal.h
@@ -22,6 +22,8 @@
 
 namespace clang {
 
+bool IsUnusedPrivateField(const FieldDecl *FD);
+
 inline bool
 FTIHasSingleVoidParameter(const DeclaratorChunk::FunctionTypeInfo &FTI) {
   return FTI.NumParams == 1 && !FTI.isVariadic &&
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 90f6f54a41fb5c..d5155f0dea1002 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -3493,7 +3493,7 @@ inline static bool HasAttribute(const QualType &T) {
   return false;
 }
 
-static bool IsUnusedPrivateField(const FieldDecl *FD) {
+bool clang::IsUnusedPrivateField(const FieldDecl *FD) {
   if (FD->isImplicit() || !FD->getDeclName() || FD->getAccess() != AS_private 
||
       FD->hasAttr<UnusedAttr>() || FD->getParent()->isDependentContext())
     return false;
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index b4881d0c6db5cb..c780f2667ced9f 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1934,6 +1934,11 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl 
*D) {
   Field->setAccess(D->getAccess());
   Owner->addDecl(Field);
 
+  if (!SemaRef.Diags.isIgnored(diag::warn_unused_private_field,
+                               Field->getLocation()) &&
+      IsUnusedPrivateField(Field))
+    SemaRef.UnusedPrivateFields.insert(Field);
+
   return Field;
 }
 
diff --git a/clang/test/SemaCXX/uninitialized.cpp 
b/clang/test/SemaCXX/uninitialized.cpp
index 9ecea1ac4cc3bd..0e90bb67840ad3 100644
--- a/clang/test/SemaCXX/uninitialized.cpp
+++ b/clang/test/SemaCXX/uninitialized.cpp
@@ -593,7 +593,7 @@ namespace rdar10398199 {
   };
   void stuff();
   template <typename T> class FooImpl : public Foo {
-    T val;
+    T val; // expected-warning 2{{private field 'val' is not used}}
   public:
     FooImpl(const T &x) : val(x) {}
     ~FooImpl() { stuff(); }
diff --git a/clang/test/SemaCXX/warn-unused-private-field.cpp 
b/clang/test/SemaCXX/warn-unused-private-field.cpp
index e8e6130801d560..650a2cffc557e3 100644
--- a/clang/test/SemaCXX/warn-unused-private-field.cpp
+++ b/clang/test/SemaCXX/warn-unused-private-field.cpp
@@ -369,10 +369,22 @@ struct Outer {
     return i.field_;
   }
 };
-
 WarnUnusedType test() {
   Outer<int> o;
   Outer<int>::Inner i;
   return o.use(i);
 }
+
+template <typename T>
+struct Outer2 {
+  class Inner {
+    WarnUnusedType field_; // expected-warning {{private field 'field_' is not 
used}}
+  };
+};
+void test2() {
+  Outer2<int> o;
+  Outer2<int>::Inner i;
+  (void)o;
+  (void)i;
+}
 } // namespace warn_unused_template

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

Reply via email to