18 auto RefField = fieldDecl(hasType(hasCanonicalType(referenceType(
19 pointee(equalsBoundNode(
"type"))))))
21 auto AssignLHS = memberExpr(
22 hasObjectExpression(ignoringParenCasts(cxxThisExpr())), member(RefField));
23 auto DerefOperand = expr(ignoringParenCasts(
24 declRefExpr(to(parmVarDecl(equalsBoundNode(
"parm"))))));
25 auto AssignRHS = expr(ignoringParenCasts(
26 unaryOperator(hasOperatorName(
"*"), hasUnaryOperand(DerefOperand))));
28 auto BinaryOpAssign = binaryOperator(hasOperatorName(
"="), hasLHS(AssignLHS),
30 auto CXXOperatorCallAssign = cxxOperatorCallExpr(
31 hasOverloadedOperatorName(
"="), hasLHS(AssignLHS), hasRHS(AssignRHS));
34 compoundStmt(statementCountIs(1),
35 anyOf(has(BinaryOpAssign), has(CXXOperatorCallAssign)));
41 parmVarDecl(hasType(hasCanonicalType(pointerType(pointee(qualType(
42 hasCanonicalType(qualType().bind(
"type"))))))))
45 .bind(
"bad-set-function");
46 Finder->addMatcher(BadSetFunction,
this);
50 const MatchFinder::MatchResult &Result) {
51 const auto *Found = Result.Nodes.getNodeAs<CXXMethodDecl>(
"bad-set-function");
52 const auto *Member = Result.Nodes.getNodeAs<FieldDecl>(
"member");
53 assert(Found !=
nullptr);
54 assert(Member !=
nullptr);
56 diag(Found->getBeginLoc(),
57 "function '%0' can be mistakenly used in order to change the "
58 "reference '%1' instead of the value of it; consider not using a "
59 "pointer as argument")
60 << Found->getName() << Member->getName();