brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.0 KiB · a444ab6 Raw
202 lines · c
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#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H11 12#include "TypeTraits.h"13#include "clang/AST/ExprConcepts.h"14#include "clang/ASTMatchers/ASTMatchers.h"15#include <optional>16 17namespace clang::tidy::matchers {18 19AST_MATCHER(BinaryOperator, isRelationalOperator) {20  return Node.isRelationalOp();21}22 23AST_MATCHER(BinaryOperator, isEqualityOperator) { return Node.isEqualityOp(); }24 25AST_MATCHER(QualType, isExpensiveToCopy) {26  std::optional<bool> IsExpensive =27      utils::type_traits::isExpensiveToCopy(Node, Finder->getASTContext());28  return IsExpensive && *IsExpensive;29}30 31AST_MATCHER(RecordDecl, isTriviallyDefaultConstructible) {32  return utils::type_traits::recordIsTriviallyDefaultConstructible(33      Node, Finder->getASTContext());34}35 36AST_MATCHER(QualType, isTriviallyDestructible) {37  return utils::type_traits::isTriviallyDestructible(Node);38}39 40// Returns QualType matcher for references to const.41AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isReferenceToConst) {42  using namespace ast_matchers;43  return referenceType(pointee(qualType(isConstQualified())));44}45 46// Returns QualType matcher for pointers to const.47AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isPointerToConst) {48  using namespace ast_matchers;49  return pointerType(pointee(qualType(isConstQualified())));50}51 52// Returns QualType matcher for target char type only.53AST_MATCHER(QualType, isSimpleChar) {54  const auto *ActualType = Node.getTypePtr();55  return ActualType &&56         (ActualType->isSpecificBuiltinType(BuiltinType::Char_S) ||57          ActualType->isSpecificBuiltinType(BuiltinType::Char_U));58}59 60AST_MATCHER(Expr, hasUnevaluatedContext) {61  if (isa<CXXNoexceptExpr>(Node) || isa<RequiresExpr>(Node))62    return true;63  if (const auto *UnaryExpr = dyn_cast<UnaryExprOrTypeTraitExpr>(&Node)) {64    switch (UnaryExpr->getKind()) {65    case UETT_SizeOf:66    case UETT_AlignOf:67      return true;68    default:69      return false;70    }71  }72  if (const auto *TypeIDExpr = dyn_cast<CXXTypeidExpr>(&Node))73    return !TypeIDExpr->isPotentiallyEvaluated();74  return false;75}76 77// A matcher implementation that matches a list of type name regular expressions78// against a NamedDecl. If a regular expression contains the substring "::"79// matching will occur against the qualified name, otherwise only the typename.80class MatchesAnyListedNameMatcher81    : public ast_matchers::internal::MatcherInterface<NamedDecl> {82public:83  explicit MatchesAnyListedNameMatcher(llvm::ArrayRef<StringRef> NameList) {84    std::transform(85        NameList.begin(), NameList.end(), std::back_inserter(NameMatchers),86        [](const llvm::StringRef Name) { return NameMatcher(Name); });87  }88 89  class NameMatcher {90    llvm::Regex Regex;91    enum class MatchMode {92      // Match against the unqualified name because the regular expression93      // does not contain ":".94      MatchUnqualified,95      // Match against the qualified name because the regular expression96      // contains ":" suggesting name and namespace should be matched.97      MatchQualified,98      // Match against the fully qualified name because the regular expression99      // starts with ":".100      MatchFullyQualified,101    };102    MatchMode Mode;103 104  public:105    NameMatcher(const llvm::StringRef Regex)106        : Regex(Regex), Mode(determineMatchMode(Regex)) {}107 108    bool match(const NamedDecl &ND) const {109      switch (Mode) {110      case MatchMode::MatchQualified:111        return Regex.match(ND.getQualifiedNameAsString());112      case MatchMode::MatchFullyQualified:113        return Regex.match("::" + ND.getQualifiedNameAsString());114      default:115        if (const IdentifierInfo *II = ND.getIdentifier())116          return Regex.match(II->getName());117        return false;118      }119    }120 121  private:122    MatchMode determineMatchMode(llvm::StringRef Regex) {123      if (Regex.starts_with(":") || Regex.starts_with("^:")) {124        return MatchMode::MatchFullyQualified;125      }126      return Regex.contains(":") ? MatchMode::MatchQualified127                                 : MatchMode::MatchUnqualified;128    }129  };130 131  bool matches(132      const NamedDecl &Node, ast_matchers::internal::ASTMatchFinder *Finder,133      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {134    return llvm::any_of(NameMatchers, [&Node](const NameMatcher &NM) {135      return NM.match(Node);136    });137  }138 139private:140  std::vector<NameMatcher> NameMatchers;141};142 143// Returns a matcher that matches NamedDecl's against a list of provided regular144// expressions. If a regular expression contains starts ':' the NamedDecl's145// qualified name will be used for matching, otherwise its name will be used.146inline ::clang::ast_matchers::internal::Matcher<NamedDecl>147matchesAnyListedName(llvm::ArrayRef<StringRef> NameList) {148  return ::clang::ast_matchers::internal::Matcher(149      new MatchesAnyListedNameMatcher(NameList));150}151 152// Predicate that verify if statement is not identical to one bound to ID node.153struct NotIdenticalStatementsPredicate {154  bool155  operator()(const clang::ast_matchers::internal::BoundNodesMap &Nodes) const;156 157  std::string ID;158  ::clang::DynTypedNode Node;159  ASTContext *Context;160};161 162// Checks if statement is identical (utils::areStatementsIdentical) to one bound163// to ID node.164AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID) {165  const NotIdenticalStatementsPredicate Predicate{166      ID, ::clang::DynTypedNode::create(Node), &(Finder->getASTContext())};167  return Builder->removeBindings(Predicate);168}169 170// A matcher implementation that matches a list of type name regular expressions171// against a QualType.172class MatchesAnyListedTypeNameMatcher173    : public ast_matchers::internal::MatcherInterface<QualType> {174public:175  explicit MatchesAnyListedTypeNameMatcher(llvm::ArrayRef<StringRef> NameList,176                                           bool CanonicalTypes);177  ~MatchesAnyListedTypeNameMatcher() override;178  bool matches(179      const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,180      ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override;181 182private:183  std::vector<llvm::Regex> NameMatchers;184  bool CanonicalTypes;185};186 187// Returns a matcher that matches QualType against a list of provided regular.188inline ::clang::ast_matchers::internal::Matcher<QualType>189matchesAnyListedTypeName(llvm::ArrayRef<StringRef> NameList,190                         bool CanonicalTypes) {191  return ::clang::ast_matchers::internal::Matcher(192      new MatchesAnyListedTypeNameMatcher(NameList, CanonicalTypes));193}194inline ::clang::ast_matchers::internal::Matcher<QualType>195matchesAnyListedTypeName(llvm::ArrayRef<StringRef> NameList) {196  return matchesAnyListedTypeName(NameList, true);197}198 199} // namespace clang::tidy::matchers200 201#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H202