Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -3729,10 +3729,20 @@ 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); } Index: clang/test/SemaCXX/warn-unused-private-field.cpp =================================================================== --- clang/test/SemaCXX/warn-unused-private-field.cpp +++ clang/test/SemaCXX/warn-unused-private-field.cpp @@ -284,3 +284,14 @@ 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 +}; +}