[clang-tools-extra] 2cd2acc - [clang-tidy] Fix false positives involving type aliases in `misc-unconventional-assign-operator` check
Fabian Wolff via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 17 12:20:33 PST 2022
Author: Fabian Wolff
Date: 2022-01-17T21:16:17+01:00
New Revision: 2cd2accc61ea0900bde66c79d1d04b29bb9e3ed7
URL: https://github.com/llvm/llvm-project/commit/2cd2accc61ea0900bde66c79d1d04b29bb9e3ed7
DIFF: https://github.com/llvm/llvm-project/commit/2cd2accc61ea0900bde66c79d1d04b29bb9e3ed7.diff
LOG: [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
Added:
Modified:
clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
clang-tools-extra/docs/clang-tidy/checks/misc-unconventional-assign-operator.rst
clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp b/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
index 594c83a30e7ef..12ba5d9997fb1 100644
--- a/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
+++ b/clang-tools-extra/clang-tidy/misc/UnconventionalAssignOperatorCheck.cpp
@@ -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,
diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc-unconventional-assign-operator.rst b/clang-tools-extra/docs/clang-tidy/checks/misc-unconventional-assign-operator.rst
index 8b85332fa0c35..49e3fd5b6ee42 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/misc-unconventional-assign-operator.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/misc-unconventional-assign-operator.rst
@@ -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
diff erent
+ type (e.g. ``int``).
* Private and deleted operators are ignored.
* The operator must always return ``*this``.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp b/clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp
index 4f0713a01f6f4..b010a8a230bcc 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp
@@ -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
diff erent 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]
+};
More information about the cfe-commits
mailing list