diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 1bd295c68b83b..1e273c1b7ce46 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -202,6 +202,9 @@ Bug Fixes in This Version - Clang now emits an error if it is not possible to deduce array size for a variable with incomplete array type. (`#37257 `_) +- Clang's ``-Wunused-private-field`` no longer warns on fields whose type is + declared with ``[[maybe_unused]]``. + (`#61334 `_) Bug Fixes to Compiler Builtins ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index a7ab0948d01bf..2b2b7391f88fd 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -3729,10 +3729,20 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (!Diags.isIgnored(diag::warn_unused_private_field, FD->getLocation())) { // Remember all explicit private FieldDecls that have a name, no side // effects and are not part of a dependent type declaration. + + auto DeclHasUnusedAttr = [](const QualType &T) { + if (const TagDecl *TD = T->getAsTagDecl()) + return TD->hasAttr(); + if (const TypedefType *TDT = T->getAs()) + return TDT->getDecl()->hasAttr(); + return false; + }; + if (!FD->isImplicit() && FD->getDeclName() && FD->getAccess() == AS_private && !FD->hasAttr() && !FD->getParent()->isDependentContext() && + !DeclHasUnusedAttr(FD->getType()) && !InitializationHasSideEffects(*FD)) UnusedPrivateFields.insert(FD); } diff --git a/clang/test/SemaCXX/warn-unused-private-field.cpp b/clang/test/SemaCXX/warn-unused-private-field.cpp index e67603eaceae6..1128eacc309d9 100644 --- a/clang/test/SemaCXX/warn-unused-private-field.cpp +++ b/clang/test/SemaCXX/warn-unused-private-field.cpp @@ -284,3 +284,14 @@ class defaulted_special_member { private: int n; // expected-warning{{private field 'n' is not used}} }; + +namespace pr61334 { +class [[maybe_unused]] MaybeUnusedClass {}; +enum [[maybe_unused]] MaybeUnusedEnum {}; +typedef int MaybeUnusedTypedef [[maybe_unused]]; +class C { + MaybeUnusedClass c; // no-warning + MaybeUnusedEnum e; // no-warning + MaybeUnusedTypedef t; // no-warning +}; +}