[clang-tidy] fix misc-unconventional-assign-operator entity match (#154430)

Makes sure UnconventionalAssignOperatorCheck checks if the types
reference the same entity, not the exact declaration.

This adds a new matcher to support this check.

This fixes a regression introduced by #147835. Since this regression was
never released, there are no release notes.

Fixes #153770
This commit is contained in:
Matheus Izvekov 2025-08-19 19:28:41 -03:00 committed by GitHub
parent 317920063b
commit 227e88b943
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 22 additions and 3 deletions

View File

@ -29,11 +29,13 @@ void UnconventionalAssignOperatorCheck::registerMatchers(
const auto HasGoodReturnType = const auto HasGoodReturnType =
cxxMethodDecl(returns(hasCanonicalType(lValueReferenceType(pointee( cxxMethodDecl(returns(hasCanonicalType(lValueReferenceType(pointee(
unless(isConstQualified()), unless(isConstQualified()),
anyOf(autoType(), hasDeclaration(equalsBoundNode("class")))))))); anyOf(autoType(),
hasDeclaration(declaresSameEntityAsBoundNode("class"))))))));
const auto IsSelf = qualType(hasCanonicalType( const auto IsSelf = qualType(hasCanonicalType(
anyOf(hasDeclaration(equalsBoundNode("class")), anyOf(hasDeclaration(declaresSameEntityAsBoundNode("class")),
referenceType(pointee(hasDeclaration(equalsBoundNode("class"))))))); referenceType(pointee(
hasDeclaration(declaresSameEntityAsBoundNode("class")))))));
const auto IsAssign = const auto IsAssign =
cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())), cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())),
hasName("operator="), ofClass(recordDecl().bind("class"))) hasName("operator="), ofClass(recordDecl().bind("class")))

View File

@ -176,3 +176,11 @@ struct TemplateAssignment {
} }
}; };
} }
namespace GH153770 {
struct A;
struct A {
A() = default;
A& operator=(const A&) = default;
};
} // namespace GH153770

View File

@ -5739,6 +5739,14 @@ AST_POLYMORPHIC_MATCHER_P(equalsBoundNode,
return Builder->removeBindings(Predicate); return Builder->removeBindings(Predicate);
} }
/// Matches a declaration if it declares the same entity as the node previously
/// bound to \p ID.
AST_MATCHER_P(Decl, declaresSameEntityAsBoundNode, std::string, ID) {
return Builder->removeBindings([&](const internal::BoundNodesMap &Nodes) {
return !clang::declaresSameEntity(&Node, Nodes.getNodeAs<Decl>(ID));
});
}
/// Matches the condition variable statement in an if statement. /// Matches the condition variable statement in an if statement.
/// ///
/// Given /// Given

View File

@ -240,6 +240,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(enumDecl); REGISTER_MATCHER(enumDecl);
REGISTER_MATCHER(enumType); REGISTER_MATCHER(enumType);
REGISTER_MATCHER(equalsBoundNode); REGISTER_MATCHER(equalsBoundNode);
REGISTER_MATCHER(declaresSameEntityAsBoundNode);
REGISTER_MATCHER(equalsIntegralValue); REGISTER_MATCHER(equalsIntegralValue);
REGISTER_MATCHER(explicitCastExpr); REGISTER_MATCHER(explicitCastExpr);
REGISTER_MATCHER(exportDecl); REGISTER_MATCHER(exportDecl);