Skip to content

Commit 55fb96c

Browse files
committed
[Clang] handle [[warn_unused]] attribute for unused private fields
1 parent 0dc086a commit 55fb96c

File tree

3 files changed

+40
-17
lines changed

3 files changed

+40
-17
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@ Improvements to Clang's diagnostics
707707
}
708708
709709
- Fix -Wdangling false positives on conditional operators (#120206).
710+
- Clang now diagnoses unused private fields with the ``[[warn_unused]]`` attribute (#GH62472).
710711

711712
Improvements to Clang's time-trace
712713
----------------------------------

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3307,6 +3307,29 @@ void Sema::CheckShadowInheritedFields(const SourceLocation &Loc,
33073307
}
33083308
}
33093309

3310+
template <typename AttrType>
3311+
inline static bool HasAttribute(const QualType &T) {
3312+
if (const TagDecl *TD = T->getAsTagDecl())
3313+
return TD->hasAttr<AttrType>();
3314+
if (const TypedefType *TDT = T->getAs<TypedefType>())
3315+
return TDT->getDecl()->hasAttr<AttrType>();
3316+
return false;
3317+
}
3318+
3319+
inline static bool IsUnusedPrivateField(FieldDecl *FD) {
3320+
if (FD->getAccess() == AS_private && FD->getDeclName()) {
3321+
QualType FieldType = FD->getType();
3322+
if (HasAttribute<WarnUnusedAttr>(FieldType))
3323+
return true;
3324+
3325+
return !FD->isImplicit() && !FD->hasAttr<UnusedAttr>() &&
3326+
!FD->getParent()->isDependentContext() &&
3327+
!HasAttribute<UnusedAttr>(FieldType) &&
3328+
!InitializationHasSideEffects(*FD);
3329+
}
3330+
return false;
3331+
}
3332+
33103333
NamedDecl *
33113334
Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
33123335
MultiTemplateParamsArg TemplateParameterLists,
@@ -3589,25 +3612,11 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
35893612
FieldDecl *FD = cast<FieldDecl>(Member);
35903613
FieldCollector->Add(FD);
35913614

3592-
if (!Diags.isIgnored(diag::warn_unused_private_field, FD->getLocation())) {
3615+
if (!Diags.isIgnored(diag::warn_unused_private_field, FD->getLocation()) &&
3616+
IsUnusedPrivateField(FD)) {
35933617
// Remember all explicit private FieldDecls that have a name, no side
35943618
// effects and are not part of a dependent type declaration.
3595-
3596-
auto DeclHasUnusedAttr = [](const QualType &T) {
3597-
if (const TagDecl *TD = T->getAsTagDecl())
3598-
return TD->hasAttr<UnusedAttr>();
3599-
if (const TypedefType *TDT = T->getAs<TypedefType>())
3600-
return TDT->getDecl()->hasAttr<UnusedAttr>();
3601-
return false;
3602-
};
3603-
3604-
if (!FD->isImplicit() && FD->getDeclName() &&
3605-
FD->getAccess() == AS_private &&
3606-
!FD->hasAttr<UnusedAttr>() &&
3607-
!FD->getParent()->isDependentContext() &&
3608-
!DeclHasUnusedAttr(FD->getType()) &&
3609-
!InitializationHasSideEffects(*FD))
3610-
UnusedPrivateFields.insert(FD);
3619+
UnusedPrivateFields.insert(FD);
36113620
}
36123621
}
36133622

clang/test/SemaCXX/warn-unused-private-field.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,3 +329,16 @@ class C {
329329
MaybeUnusedTypedef t; // no-warning
330330
};
331331
}
332+
333+
namespace GH62472 {
334+
class [[gnu::warn_unused]] S {
335+
public:
336+
S();
337+
};
338+
339+
class C {
340+
private:
341+
const int i = 0; // expected-warning {{private field 'i' is not used}}
342+
const S s; // expected-warning {{private field 's' is not used}}
343+
};
344+
}

0 commit comments

Comments
 (0)