brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.3 KiB · 2469da9 Raw
84 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 "NoAutomaticMoveCheck.h"10#include "../utils/Matchers.h"11#include "../utils/OptionsUtils.h"12#include "clang/AST/ASTContext.h"13#include "clang/ASTMatchers/ASTMatchFinder.h"14 15using namespace clang::ast_matchers;16 17namespace clang::tidy::performance {18 19namespace {20 21AST_MATCHER(VarDecl, isNRVOVariable) { return Node.isNRVOVariable(); }22 23} // namespace24 25NoAutomaticMoveCheck::NoAutomaticMoveCheck(StringRef Name,26                                           ClangTidyContext *Context)27    : ClangTidyCheck(Name, Context),28      AllowedTypes(29          utils::options::parseStringList(Options.get("AllowedTypes", ""))) {}30 31void NoAutomaticMoveCheck::registerMatchers(MatchFinder *Finder) {32  const auto NonNrvoConstLocalVariable =33      varDecl(hasLocalStorage(), unless(hasType(lValueReferenceType())),34              unless(isNRVOVariable()),35              hasType(qualType(36                  isConstQualified(),37                  hasCanonicalType(matchers::isExpensiveToCopy()),38                  unless(hasDeclaration(namedDecl(39                      matchers::matchesAnyListedName(AllowedTypes)))))))40          .bind("vardecl");41 42  // A matcher for a `DstT::DstT(const Src&)` where DstT also has a43  // `DstT::DstT(Src&&)`.44  const auto LValueRefCtor = cxxConstructorDecl(45      hasParameter(0, hasType(hasCanonicalType(46                          lValueReferenceType(pointee(type().bind("SrcT")))))),47      ofClass(cxxRecordDecl(hasMethod(cxxConstructorDecl(48          hasParameter(0, hasType(hasCanonicalType(rValueReferenceType(49                              pointee(type(equalsBoundNode("SrcT"))))))))))));50 51  // A matcher for `DstT::DstT(const Src&&)`, which typically comes from an52  // instantiation of `template <typename U> DstT::DstT(U&&)`.53  const auto ConstRefRefCtor = cxxConstructorDecl(54      parameterCountIs(1),55      hasParameter(0,56                   hasType(rValueReferenceType(pointee(isConstQualified())))));57 58  Finder->addMatcher(59      traverse(60          TK_AsIs,61          returnStmt(hasReturnValue(62              ignoringElidableConstructorCall(ignoringParenImpCasts(63                  cxxConstructExpr(64                      hasDeclaration(anyOf(LValueRefCtor, ConstRefRefCtor)),65                      hasArgument(0, ignoringParenImpCasts(declRefExpr(66                                         to(NonNrvoConstLocalVariable)))))67                      .bind("ctor_call")))))),68      this);69}70 71void NoAutomaticMoveCheck::check(const MatchFinder::MatchResult &Result) {72  const auto *Var = Result.Nodes.getNodeAs<VarDecl>("vardecl");73  const auto *CtorCall = Result.Nodes.getNodeAs<Expr>("ctor_call");74  diag(CtorCall->getExprLoc(), "constness of '%0' prevents automatic move")75      << Var->getName();76}77 78void NoAutomaticMoveCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {79  Options.store(Opts, "AllowedTypes",80                utils::options::serializeStringList(AllowedTypes));81}82 83} // namespace clang::tidy::performance84