brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.8 KiB · cbbb1a0 Raw
75 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "CopyConstructorMutatesArgumentCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/ASTMatchers/ASTMatchFinder.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::bugprone {16 17static constexpr llvm::StringLiteral SourceDeclName = "ChangedPVD";18static constexpr llvm::StringLiteral MutatingOperatorName = "MutatingOp";19static constexpr llvm::StringLiteral MutatingCallName = "MutatingCall";20 21void CopyConstructorMutatesArgumentCheck::registerMatchers(22    MatchFinder *Finder) {23  const auto MemberExprOrSourceObject = anyOf(24      memberExpr(),25      declRefExpr(to(decl(equalsBoundNode(std::string(SourceDeclName))))));26 27  const auto IsPartOfSource =28      allOf(unless(hasDescendant(expr(unless(MemberExprOrSourceObject)))),29            MemberExprOrSourceObject);30 31  const auto IsSourceMutatingAssignment = traverse(32      TK_AsIs, binaryOperation(hasOperatorName("="), hasLHS(IsPartOfSource))33                   .bind(MutatingOperatorName));34 35  const auto MemberExprOrSelf = anyOf(memberExpr(), cxxThisExpr());36 37  const auto IsPartOfSelf = allOf(38      unless(hasDescendant(expr(unless(MemberExprOrSelf)))), MemberExprOrSelf);39 40  const auto IsSelfMutatingAssignment =41      binaryOperation(isAssignmentOperator(), hasLHS(IsPartOfSelf));42 43  const auto IsSelfMutatingMemberFunction =44      functionDecl(hasBody(hasDescendant(IsSelfMutatingAssignment)));45 46  const auto IsSourceMutatingMemberCall =47      cxxMemberCallExpr(on(IsPartOfSource),48                        callee(IsSelfMutatingMemberFunction))49          .bind(MutatingCallName);50 51  const auto MutatesSource = allOf(52      hasParameter(53          0, parmVarDecl(hasType(lValueReferenceType())).bind(SourceDeclName)),54      anyOf(forEachDescendant(IsSourceMutatingAssignment),55            forEachDescendant(IsSourceMutatingMemberCall)));56 57  Finder->addMatcher(cxxConstructorDecl(isCopyConstructor(), MutatesSource),58                     this);59 60  Finder->addMatcher(cxxMethodDecl(isCopyAssignmentOperator(), MutatesSource),61                     this);62}63 64void CopyConstructorMutatesArgumentCheck::check(65    const MatchFinder::MatchResult &Result) {66  if (const auto *MemberCall =67          Result.Nodes.getNodeAs<CXXMemberCallExpr>(MutatingCallName))68    diag(MemberCall->getBeginLoc(), "call mutates copied object");69  else if (const auto *Assignment =70               Result.Nodes.getNodeAs<Expr>(MutatingOperatorName))71    diag(Assignment->getBeginLoc(), "mutating copied object");72}73 74} // namespace clang::tidy::bugprone75