[clang-tidy] Skip union-like classes in use-equals-default

Skip unions/union-like classes since in this case constructors
with empty bodies behave differently in comparison with regular
structs/classes.

Test plan: ninja check-clang-tools

Differential revision: https://reviews.llvm.org/D132713
This commit is contained in:
Alexander Shaposhnikov 2022-09-06 20:19:47 +00:00
parent b4257d3bf5
commit 44503482e0
4 changed files with 40 additions and 11 deletions

View File

@ -218,17 +218,20 @@ void UseEqualsDefaultCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
}
void UseEqualsDefaultCheck::registerMatchers(MatchFinder *Finder) {
// Skip unions since constructors with empty bodies behave differently
// in comparison with structs/classes.
// Skip unions/union-like classes since their constructors behave differently
// when defaulted vs. empty.
auto IsUnionLikeClass = recordDecl(
anyOf(isUnion(),
has(fieldDecl(isImplicit(), hasType(cxxRecordDecl(isUnion()))))));
// Destructor.
Finder->addMatcher(cxxDestructorDecl(unless(hasParent(recordDecl(isUnion()))),
isDefinition())
.bind(SpecialFunction),
this);
Finder->addMatcher(
cxxDestructorDecl(unless(hasParent(IsUnionLikeClass)), isDefinition())
.bind(SpecialFunction),
this);
Finder->addMatcher(
cxxConstructorDecl(
unless(hasParent(recordDecl(isUnion()))), isDefinition(),
unless(hasParent(IsUnionLikeClass)), isDefinition(),
anyOf(
// Default constructor.
allOf(unless(hasAnyConstructorInitializer(isWritten())),
@ -243,7 +246,7 @@ void UseEqualsDefaultCheck::registerMatchers(MatchFinder *Finder) {
this);
// Copy-assignment operator.
Finder->addMatcher(
cxxMethodDecl(unless(hasParent(recordDecl(isUnion()))), isDefinition(),
cxxMethodDecl(unless(hasParent(IsUnionLikeClass)), isDefinition(),
isCopyAssignmentOperator(),
// isCopyAssignmentOperator() allows the parameter to be
// passed by value, and in this case it cannot be

View File

@ -144,9 +144,10 @@ Changes in existing checks
- Improved :doc:`modernize-use-equals-default <clang-tidy/checks/modernize/use-equals-default>`
check.
The check now skips unions since in this case a default constructor with empty body
is not equivalent to the explicitly defaulted one. The check also skips copy assignment
operators with nonstandard return types. The check is restricted to c++11-or-later.
The check now skips unions/union-like classes since in this case a default constructor
with empty body is not equivalent to the explicitly defaulted one. The check also skips
copy assignment operators with nonstandard return types. The check is restricted to
c++11-or-later.
Removed checks
^^^^^^^^^^^^^^

View File

@ -44,6 +44,20 @@ union NU {
IL Field;
};
// Skip structs/classes containing anonymous unions.
struct SU {
SU(const SU &Other) : Field(Other.Field) {}
// CHECK-FIXES: SU(const SU &Other) :
SU &operator=(const SU &Other) {
Field = Other.Field;
return *this;
}
// CHECK-FIXES: SU &operator=(const SU &Other) {
union {
IL Field;
};
};
// Wrong type.
struct WT {
WT(const IL &Other) {}

View File

@ -42,6 +42,17 @@ union NU {
NE Field;
};
// Skip structs/classes containing anonymous unions.
struct SU {
SU() {}
// CHECK-FIXES: SU() {}
~SU() {}
// CHECK-FIXES: ~SU() {}
union {
NE Field;
};
};
// Initializer or arguments.
class IA {
public: