clang-tools 22.0.0git
MisleadingSetterOfReferenceCheck.cpp
Go to the documentation of this file.
1//===--- MisleadingSetterOfReferenceCheck.cpp - clang-tidy-----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12
13using namespace clang::ast_matchers;
14
15namespace clang::tidy::bugprone {
16
18 auto RefField = fieldDecl(hasType(hasCanonicalType(referenceType(
19 pointee(equalsBoundNode("type"))))))
20 .bind("member");
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))));
27
28 auto BinaryOpAssign = binaryOperator(hasOperatorName("="), hasLHS(AssignLHS),
29 hasRHS(AssignRHS));
30 auto CXXOperatorCallAssign = cxxOperatorCallExpr(
31 hasOverloadedOperatorName("="), hasLHS(AssignLHS), hasRHS(AssignRHS));
32
33 auto SetBody =
34 compoundStmt(statementCountIs(1),
35 anyOf(has(BinaryOpAssign), has(CXXOperatorCallAssign)));
36 auto BadSetFunction =
37 cxxMethodDecl(
38 parameterCountIs(1),
39 hasParameter(
40 0,
41 parmVarDecl(hasType(hasCanonicalType(pointerType(pointee(qualType(
42 hasCanonicalType(qualType().bind("type"))))))))
43 .bind("parm")),
44 hasBody(SetBody))
45 .bind("bad-set-function");
46 Finder->addMatcher(BadSetFunction, this);
47}
48
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);
55
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();
61}
62
63} // namespace clang::tidy::bugprone
void registerMatchers(ast_matchers::MatchFinder *Finder) override
void check(const ast_matchers::MatchFinder::MatchResult &Result) override