10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 23 void MutatingCopyCheck::registerMatchers(MatchFinder *Finder) {
24 if (!getLangOpts().CPlusPlus)
27 const auto MemberExprOrSourceObject = anyOf(
28 memberExpr(), declRefExpr(to(decl(equalsBoundNode(SourceDeclName)))));
30 const auto IsPartOfSource =
31 allOf(unless(hasDescendant(expr(unless(MemberExprOrSourceObject)))),
32 MemberExprOrSourceObject);
34 const auto IsSourceMutatingAssignment =
35 expr(anyOf(binaryOperator(isAssignmentOperator(), hasLHS(IsPartOfSource))
36 .bind(MutatingOperatorName),
37 cxxOperatorCallExpr(isAssignmentOperator(),
38 hasArgument(0, IsPartOfSource))
39 .bind(MutatingOperatorName)));
41 const auto MemberExprOrSelf = anyOf(memberExpr(), cxxThisExpr());
43 const auto IsPartOfSelf = allOf(
44 unless(hasDescendant(expr(unless(MemberExprOrSelf)))), MemberExprOrSelf);
46 const auto IsSelfMutatingAssignment =
47 expr(anyOf(binaryOperator(isAssignmentOperator(), hasLHS(IsPartOfSelf)),
48 cxxOperatorCallExpr(isAssignmentOperator(),
49 hasArgument(0, IsPartOfSelf))));
51 const auto IsSelfMutatingMemberFunction =
52 functionDecl(hasBody(hasDescendant(IsSelfMutatingAssignment)));
54 const auto IsSourceMutatingMemberCall =
55 cxxMemberCallExpr(on(IsPartOfSource),
56 callee(IsSelfMutatingMemberFunction))
57 .bind(MutatingCallName);
59 const auto MutatesSource = allOf(
61 0, parmVarDecl(hasType(lValueReferenceType())).bind(SourceDeclName)),
62 anyOf(forEachDescendant(IsSourceMutatingAssignment),
63 forEachDescendant(IsSourceMutatingMemberCall)));
65 Finder->addMatcher(cxxConstructorDecl(isCopyConstructor(), MutatesSource),
68 Finder->addMatcher(cxxMethodDecl(isCopyAssignmentOperator(), MutatesSource),
72 void MutatingCopyCheck::check(
const MatchFinder::MatchResult &Result) {
73 if (
const auto *MemberCall =
74 Result.Nodes.getNodeAs<CXXMemberCallExpr>(MutatingCallName))
75 diag(MemberCall->getBeginLoc(),
"call mutates copied object");
76 else if (
const auto *Assignment =
77 Result.Nodes.getNodeAs<Expr>(MutatingOperatorName))
78 diag(Assignment->getBeginLoc(),
"mutating copied object");
static constexpr llvm::StringLiteral MutatingCallName
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static constexpr llvm::StringLiteral SourceDeclName
static constexpr llvm::StringLiteral MutatingOperatorName