Mercurial > hg > CbC > CbC_llvm
view clang-tools-extra/clang-tidy/cert/MutatingCopyCheck.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 79ff65ed7e25 |
children | 1f2b6ac9f198 |
line wrap: on
line source
//===--- MutatingCopyCheck.cpp - clang-tidy -------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "MutatingCopyCheck.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; namespace clang { namespace tidy { namespace cert { static constexpr llvm::StringLiteral SourceDeclName = "ChangedPVD"; static constexpr llvm::StringLiteral MutatingOperatorName = "MutatingOp"; static constexpr llvm::StringLiteral MutatingCallName = "MutatingCall"; void MutatingCopyCheck::registerMatchers(MatchFinder *Finder) { const auto MemberExprOrSourceObject = anyOf( memberExpr(), declRefExpr(to(decl(equalsBoundNode(std::string(SourceDeclName)))))); const auto IsPartOfSource = allOf(unless(hasDescendant(expr(unless(MemberExprOrSourceObject)))), MemberExprOrSourceObject); const auto IsSourceMutatingAssignment = traverse( TK_AsIs, binaryOperation(hasOperatorName("="), hasLHS(IsPartOfSource)) .bind(MutatingOperatorName)); const auto MemberExprOrSelf = anyOf(memberExpr(), cxxThisExpr()); const auto IsPartOfSelf = allOf( unless(hasDescendant(expr(unless(MemberExprOrSelf)))), MemberExprOrSelf); const auto IsSelfMutatingAssignment = binaryOperation(isAssignmentOperator(), hasLHS(IsPartOfSelf)); const auto IsSelfMutatingMemberFunction = functionDecl(hasBody(hasDescendant(IsSelfMutatingAssignment))); const auto IsSourceMutatingMemberCall = cxxMemberCallExpr(on(IsPartOfSource), callee(IsSelfMutatingMemberFunction)) .bind(MutatingCallName); const auto MutatesSource = allOf( hasParameter( 0, parmVarDecl(hasType(lValueReferenceType())).bind(SourceDeclName)), anyOf(forEachDescendant(IsSourceMutatingAssignment), forEachDescendant(IsSourceMutatingMemberCall))); Finder->addMatcher(cxxConstructorDecl(isCopyConstructor(), MutatesSource), this); Finder->addMatcher(cxxMethodDecl(isCopyAssignmentOperator(), MutatesSource), this); } void MutatingCopyCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *MemberCall = Result.Nodes.getNodeAs<CXXMemberCallExpr>(MutatingCallName)) diag(MemberCall->getBeginLoc(), "call mutates copied object"); else if (const auto *Assignment = Result.Nodes.getNodeAs<Expr>(MutatingOperatorName)) diag(Assignment->getBeginLoc(), "mutating copied object"); } } // namespace cert } // namespace tidy } // namespace clang