================ @@ -0,0 +1,122 @@ +//===--- LostStdMoveCheck.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 "LostStdMoveCheck.h" +#include "../utils/DeclRefExprUtils.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::performance { + +using utils::decl_ref_expr::allDeclRefExprs; + +AST_MATCHER(CXXRecordDecl, hasTrivialMoveConstructor) { + return Node.hasDefinition() && Node.hasTrivialMoveConstructor(); +} + +void LostStdMoveCheck::registerMatchers(MatchFinder *Finder) { + auto returnParent = + hasParent(expr(hasParent(cxxConstructExpr(hasParent(returnStmt()))))); + + auto outermostExpr = expr(unless(hasParent(expr()))); + auto leafStatement = + stmt(outermostExpr, unless(hasDescendant(outermostExpr))); + + Finder->addMatcher( + declRefExpr( + // not "return x;" + unless(returnParent), + + unless(hasType(namedDecl(hasName("::std::string_view")))), + + // non-trivial type + hasType(hasCanonicalType(hasDeclaration(cxxRecordDecl()))), + + // non-trivial X(X&&) + unless(hasType(hasCanonicalType( + hasDeclaration(cxxRecordDecl(hasTrivialMoveConstructor()))))), + + // Not in a cycle + unless(hasAncestor(forStmt())), unless(hasAncestor(doStmt())), + unless(hasAncestor(whileStmt())), + + // only non-X& + unless(hasDeclaration( + varDecl(hasType(qualType(lValueReferenceType()))))), + + hasAncestor(leafStatement.bind("leaf_statement")), + + hasDeclaration( + varDecl(hasAncestor(functionDecl().bind("func"))).bind("decl")), + + hasParent(expr(hasParent(cxxConstructExpr())).bind("use_parent"))) + .bind("use"), + this); +} + +const Expr *LostStdMoveCheck::getLastVarUsage(const VarDecl &Var, + const Decl &Func, + ASTContext &Context) { + auto Exprs = allDeclRefExprs(Var, Func, Context); + + const Expr *LastExpr = nullptr; + for (const auto &Expr : Exprs) { + if (!LastExpr) + LastExpr = Expr; + + if (LastExpr->getBeginLoc() < Expr->getBeginLoc()) + LastExpr = Expr; + } + + return LastExpr; +} + +template <typename Node> +void extractNodesByIdTo(ArrayRef<BoundNodes> Matches, StringRef ID, + llvm::SmallPtrSet<const Node *, 16> &Nodes) { + for (const auto &Match : Matches) + Nodes.insert(Match.getNodeAs<Node>(ID)); +} + +void LostStdMoveCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedDecl = Result.Nodes.getNodeAs<VarDecl>("decl"); + const auto *MatchedFunc = Result.Nodes.getNodeAs<FunctionDecl>("func"); + const auto *MatchedUse = Result.Nodes.getNodeAs<Expr>("use"); + const auto *MatchedUseCall = Result.Nodes.getNodeAs<CallExpr>("use_parent"); + const auto *MatchedLeafStatement = + Result.Nodes.getNodeAs<Stmt>("leaf_statement"); + + if (MatchedUseCall) + return; + + const auto *LastUsage = ---------------- EugeneZelenko wrote:
Ditto. https://github.com/llvm/llvm-project/pull/139525 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits