Skip to content

Commit 9efdebc

Browse files
authored
[Clang] Only ignore special methods for unused private fields in BuildFieldReferenceExpr (#116965)
The original code assumed that only special methods might be defined as defaulted. Since C++20 comparison operators might be defaulted too, and we *do* want to consider those as using the fields of the class. Fixes: #116961
1 parent ab6677e commit 9efdebc

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,8 @@ Improvements to Clang's diagnostics
591591
- For an rvalue reference bound to a temporary struct with an integer member, Clang will detect constant integer overflow
592592
in the initializer for the integer member (#GH46755).
593593

594+
- Fixed a false negative ``-Wunused-private-field`` diagnostic when a defaulted comparison operator is defined out of class (#GH116961).
595+
594596
Improvements to Clang's time-trace
595597
----------------------------------
596598

clang/lib/Sema/SemaExprMember.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1874,8 +1874,16 @@ Sema::BuildFieldReferenceExpr(Expr *BaseExpr, bool IsArrow,
18741874
Context.getAttributedType(attr::NoDeref, MemberType, MemberType);
18751875
}
18761876

1877-
auto *CurMethod = dyn_cast<CXXMethodDecl>(CurContext);
1878-
if (!(CurMethod && CurMethod->isDefaulted()))
1877+
auto isDefaultedSpecialMember = [this](const DeclContext *Ctx) {
1878+
auto *Method = dyn_cast<CXXMethodDecl>(CurContext);
1879+
if (!Method || !Method->isDefaulted())
1880+
return false;
1881+
1882+
return getDefaultedFunctionKind(Method).isSpecialMember();
1883+
};
1884+
1885+
// Implicit special members should not mark fields as used.
1886+
if (!isDefaultedSpecialMember(CurContext))
18791887
UnusedPrivateFields.remove(Field);
18801888

18811889
ExprResult Base = PerformObjectMemberConversion(BaseExpr, SS.getScopeRep(),

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,26 @@ class SpaceShipDefaultCompare {
2020
int operator<=>(const SpaceShipDefaultCompare &) const = default;
2121
};
2222

23+
class EqDefaultCompareOutOfClass {
24+
int used; // no warning, the compiler generated AST for the comparison operator
25+
// references the fields of the class, and this should be considered
26+
// a use.
27+
// This test case is needed because clang does not emit the body
28+
// of the defaulted operator when it is defined in-class until it
29+
// finds a call to it. `-Wunused-private-field` is suppressed in
30+
// a different way in that case.
31+
bool operator==(const EqDefaultCompareOutOfClass &) const;
32+
};
33+
34+
bool EqDefaultCompareOutOfClass::operator==(const EqDefaultCompareOutOfClass &) const = default;
35+
36+
class FriendEqDefaultCompareOutOfClass {
37+
int used; // no warning, same reasoning just tested via a friend declaration.
38+
friend bool operator==(const FriendEqDefaultCompareOutOfClass &, const FriendEqDefaultCompareOutOfClass &);
39+
};
40+
41+
bool operator==(const FriendEqDefaultCompareOutOfClass &, const FriendEqDefaultCompareOutOfClass &) = default;
42+
2343
#endif
2444

2545
class NotFullyDefined {

0 commit comments

Comments
 (0)