31 const auto IsUserDefined = cxxMethodDecl(
32 isDefinition(), unless(anyOf(isDeleted(), isImplicit(), isDefaulted())));
36 const auto HasReferenceParam =
37 cxxMethodDecl(hasParameter(0, parmVarDecl(hasType(referenceType()))));
41 const auto HasNoSelfCheck = cxxMethodDecl(unless(hasDescendant(
42 binaryOperation(hasAnyOperatorName(
"==",
"!="),
43 hasEitherOperand(ignoringParenCasts(cxxThisExpr()))))));
48 const auto HasNonTemplateSelfCopy = cxxMethodDecl(
49 ofClass(cxxRecordDecl(unless(hasAncestor(classTemplateDecl())))),
51 hasDescendant(cxxConstructExpr(hasDeclaration(cxxConstructorDecl(
52 isCopyConstructor(), ofClass(equalsBoundNode(
"class"))))))));
57 const auto HasTemplateSelfCopy = cxxMethodDecl(
58 ofClass(cxxRecordDecl(hasAncestor(classTemplateDecl()))),
60 varDecl(hasType(cxxRecordDecl(equalsBoundNode(
"class"))),
61 hasDescendant(parenListExpr()))),
62 hasDescendant(cxxUnresolvedConstructExpr(hasDescendant(declRefExpr(
63 hasType(cxxRecordDecl(equalsBoundNode(
"class")))))))));
68 const auto HasNoNestedSelfAssign =
69 cxxMethodDecl(unless(hasDescendant(cxxMemberCallExpr(callee(cxxMethodDecl(
70 hasName(
"operator="), ofClass(equalsBoundNode(
"class"))))))));
78 const auto HasCopyAndSwap = cxxMethodDecl(
79 ofClass(cxxRecordDecl()),
82 varDecl(hasType(cxxRecordDecl(equalsBoundNode(
"class"))))
84 hasDescendant(stmt(anyOf(
85 cxxMemberCallExpr(hasArgument(
86 0, declRefExpr(to(varDecl(equalsBoundNode(
"tmp_var")))))),
88 callee(functionDecl(hasName(
"swap"))), argumentCountIs(2),
90 declRefExpr(to(varDecl(equalsBoundNode(
"tmp_var"))))),
91 hasAnyArgument(unaryOperator(has(cxxThisExpr()),
92 hasOperatorName(
"*"))))))))));
94 DeclarationMatcher AdditionalMatcher = cxxMethodDecl();
95 if (WarnOnlyIfThisHasSuspiciousField) {
97 const auto SmartPointerType = qualType(hasUnqualifiedDesugaredType(
98 recordType(hasDeclaration(classTemplateSpecializationDecl(
99 anyOf(allOf(hasAnyName(
"::std::shared_ptr",
"::std::weak_ptr",
101 templateArgumentCountIs(1)),
102 allOf(hasName(
"::std::unique_ptr"),
103 templateArgumentCountIs(2))))))));
109 AdditionalMatcher = cxxMethodDecl(ofClass(cxxRecordDecl(
110 has(fieldDecl(anyOf(hasType(pointerType()), hasType(SmartPointerType),
111 hasType(arrayType())))))));
116 ofClass(cxxRecordDecl().bind(
"class")), isCopyAssignmentOperator(),
117 IsUserDefined, HasReferenceParam, HasNoSelfCheck,
118 unless(HasNonTemplateSelfCopy), unless(HasTemplateSelfCopy),
119 unless(HasCopyAndSwap), HasNoNestedSelfAssign, AdditionalMatcher)
120 .bind(
"copyAssignmentOperator"),
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.