[clang-tidy] Fix false positives involving type aliases in `misc-unconventional-assign-operator` check
clang-tidy currently reports false positives even for simple cases such as: ``` struct S { using X = S; X &operator=(const X&) { return *this; } }; ``` This is due to the fact that the `misc-unconventional-assign-operator` check fails to look at the //canonical// types. This patch fixes this behavior. Reviewed By: aaron.ballman, mizvekov Differential Revision: https://reviews.llvm.org/D114197
This commit is contained in:
parent
c10cbb243c
commit
2cd2accc61
|
@ -18,13 +18,14 @@ namespace misc {
|
|||
|
||||
void UnconventionalAssignOperatorCheck::registerMatchers(
|
||||
ast_matchers::MatchFinder *Finder) {
|
||||
const auto HasGoodReturnType = cxxMethodDecl(returns(lValueReferenceType(
|
||||
pointee(unless(isConstQualified()),
|
||||
anyOf(autoType(), hasDeclaration(equalsBoundNode("class")))))));
|
||||
const auto HasGoodReturnType =
|
||||
cxxMethodDecl(returns(hasCanonicalType(lValueReferenceType(pointee(
|
||||
unless(isConstQualified()),
|
||||
anyOf(autoType(), hasDeclaration(equalsBoundNode("class"))))))));
|
||||
|
||||
const auto IsSelf = qualType(
|
||||
const auto IsSelf = qualType(hasCanonicalType(
|
||||
anyOf(hasDeclaration(equalsBoundNode("class")),
|
||||
referenceType(pointee(hasDeclaration(equalsBoundNode("class"))))));
|
||||
referenceType(pointee(hasDeclaration(equalsBoundNode("class")))))));
|
||||
const auto IsAssign =
|
||||
cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())),
|
||||
hasName("operator="), ofClass(recordDecl().bind("class")))
|
||||
|
@ -37,9 +38,9 @@ void UnconventionalAssignOperatorCheck::registerMatchers(
|
|||
cxxMethodDecl(IsAssign, unless(HasGoodReturnType)).bind("ReturnType"),
|
||||
this);
|
||||
|
||||
const auto BadSelf = referenceType(
|
||||
const auto BadSelf = qualType(hasCanonicalType(referenceType(
|
||||
anyOf(lValueReferenceType(pointee(unless(isConstQualified()))),
|
||||
rValueReferenceType(pointee(isConstQualified()))));
|
||||
rValueReferenceType(pointee(isConstQualified()))))));
|
||||
|
||||
Finder->addMatcher(
|
||||
cxxMethodDecl(IsSelfAssign,
|
||||
|
|
|
@ -8,6 +8,8 @@ Finds declarations of assign operators with the wrong return and/or argument
|
|||
types and definitions with good return type but wrong ``return`` statements.
|
||||
|
||||
* The return type must be ``Class&``.
|
||||
* Works with move-assign and assign by value.
|
||||
* The assignment may be from the class type by value, const lvalue
|
||||
reference, non-const rvalue reference, or from a completely different
|
||||
type (e.g. ``int``).
|
||||
* Private and deleted operators are ignored.
|
||||
* The operator must always return ``*this``.
|
||||
|
|
|
@ -127,3 +127,39 @@ struct AssignmentCallAtReturn {
|
|||
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator=() should always return '*this'
|
||||
}
|
||||
};
|
||||
|
||||
// Check that no false positives are issued when using type aliases.
|
||||
struct TypeAlias {
|
||||
using Alias = TypeAlias;
|
||||
// This is correct and should not produce any warnings:
|
||||
Alias &operator=(const Alias &) { return *this; }
|
||||
|
||||
using AliasRef = Alias &;
|
||||
// So is this (assignments from other types are fine):
|
||||
AliasRef operator=(int) { return *this; }
|
||||
};
|
||||
|
||||
// Same check as above with typedef instead of using
|
||||
struct TypeAliasTypedef {
|
||||
typedef TypeAliasTypedef Alias;
|
||||
Alias &operator=(const Alias &) { return *this; }
|
||||
|
||||
typedef Alias &AliasRef;
|
||||
AliasRef operator=(int) { return *this; }
|
||||
};
|
||||
|
||||
// Same check as above for a template class
|
||||
template <typename T>
|
||||
struct TemplateTypeAlias {
|
||||
using Alias1 = TemplateTypeAlias &;
|
||||
using Alias2 = TemplateTypeAlias const &;
|
||||
Alias1 operator=(Alias2) { return *this; }
|
||||
|
||||
template <typename U>
|
||||
using Alias3 = TemplateTypeAlias<U>;
|
||||
Alias3<T> &operator=(int) { return *this; }
|
||||
|
||||
// Using a different type parameter in the return type should give a warning
|
||||
Alias3<TypeAlias::Alias> &operator=(double) { return *this; }
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: operator=() should return 'TemplateTypeAlias&' [misc-unconventional-assign-operator]
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue