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
