Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:22

0001 //===--- Matchers.h - clang-tidy-------------------------------------------===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
0010 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H
0011 
0012 #include "TypeTraits.h"
0013 #include "clang/AST/ExprConcepts.h"
0014 #include "clang/ASTMatchers/ASTMatchers.h"
0015 #include <optional>
0016 
0017 namespace clang::tidy::matchers {
0018 
0019 AST_MATCHER(BinaryOperator, isRelationalOperator) {
0020   return Node.isRelationalOp();
0021 }
0022 
0023 AST_MATCHER(BinaryOperator, isEqualityOperator) { return Node.isEqualityOp(); }
0024 
0025 AST_MATCHER(QualType, isExpensiveToCopy) {
0026   std::optional<bool> IsExpensive =
0027       utils::type_traits::isExpensiveToCopy(Node, Finder->getASTContext());
0028   return IsExpensive && *IsExpensive;
0029 }
0030 
0031 AST_MATCHER(RecordDecl, isTriviallyDefaultConstructible) {
0032   return utils::type_traits::recordIsTriviallyDefaultConstructible(
0033       Node, Finder->getASTContext());
0034 }
0035 
0036 AST_MATCHER(QualType, isTriviallyDestructible) {
0037   return utils::type_traits::isTriviallyDestructible(Node);
0038 }
0039 
0040 // Returns QualType matcher for references to const.
0041 AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isReferenceToConst) {
0042   using namespace ast_matchers;
0043   return referenceType(pointee(qualType(isConstQualified())));
0044 }
0045 
0046 // Returns QualType matcher for pointers to const.
0047 AST_MATCHER_FUNCTION(ast_matchers::TypeMatcher, isPointerToConst) {
0048   using namespace ast_matchers;
0049   return pointerType(pointee(qualType(isConstQualified())));
0050 }
0051 
0052 // Returns QualType matcher for target char type only.
0053 AST_MATCHER(QualType, isSimpleChar) {
0054   const auto ActualType = Node.getTypePtr();
0055   return ActualType &&
0056          (ActualType->isSpecificBuiltinType(BuiltinType::Char_S) ||
0057           ActualType->isSpecificBuiltinType(BuiltinType::Char_U));
0058 }
0059 
0060 AST_MATCHER(Expr, hasUnevaluatedContext) {
0061   if (isa<CXXNoexceptExpr>(Node) || isa<RequiresExpr>(Node))
0062     return true;
0063   if (const auto *UnaryExpr = dyn_cast<UnaryExprOrTypeTraitExpr>(&Node)) {
0064     switch (UnaryExpr->getKind()) {
0065     case UETT_SizeOf:
0066     case UETT_AlignOf:
0067       return true;
0068     default:
0069       return false;
0070     }
0071   }
0072   if (const auto *TypeIDExpr = dyn_cast<CXXTypeidExpr>(&Node))
0073     return !TypeIDExpr->isPotentiallyEvaluated();
0074   return false;
0075 }
0076 
0077 // A matcher implementation that matches a list of type name regular expressions
0078 // against a NamedDecl. If a regular expression contains the substring "::"
0079 // matching will occur against the qualified name, otherwise only the typename.
0080 class MatchesAnyListedNameMatcher
0081     : public ast_matchers::internal::MatcherInterface<NamedDecl> {
0082 public:
0083   explicit MatchesAnyListedNameMatcher(llvm::ArrayRef<StringRef> NameList) {
0084     std::transform(
0085         NameList.begin(), NameList.end(), std::back_inserter(NameMatchers),
0086         [](const llvm::StringRef Name) { return NameMatcher(Name); });
0087   }
0088 
0089   class NameMatcher {
0090     llvm::Regex Regex;
0091     enum class MatchMode {
0092       // Match against the unqualified name because the regular expression
0093       // does not contain ":".
0094       MatchUnqualified,
0095       // Match against the qualified name because the regular expression
0096       // contains ":" suggesting name and namespace should be matched.
0097       MatchQualified,
0098       // Match against the fully qualified name because the regular expression
0099       // starts with ":".
0100       MatchFullyQualified,
0101     };
0102     MatchMode Mode;
0103 
0104   public:
0105     NameMatcher(const llvm::StringRef Regex)
0106         : Regex(Regex), Mode(determineMatchMode(Regex)) {}
0107 
0108     bool match(const NamedDecl &ND) const {
0109       switch (Mode) {
0110       case MatchMode::MatchQualified:
0111         return Regex.match(ND.getQualifiedNameAsString());
0112       case MatchMode::MatchFullyQualified:
0113         return Regex.match("::" + ND.getQualifiedNameAsString());
0114       default:
0115         if (const IdentifierInfo *II = ND.getIdentifier())
0116           return Regex.match(II->getName());
0117         return false;
0118       }
0119     }
0120 
0121   private:
0122     MatchMode determineMatchMode(llvm::StringRef Regex) {
0123       if (Regex.starts_with(":") || Regex.starts_with("^:")) {
0124         return MatchMode::MatchFullyQualified;
0125       }
0126       return Regex.contains(":") ? MatchMode::MatchQualified
0127                                  : MatchMode::MatchUnqualified;
0128     }
0129   };
0130 
0131   bool matches(
0132       const NamedDecl &Node, ast_matchers::internal::ASTMatchFinder *Finder,
0133       ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override {
0134     return llvm::any_of(NameMatchers, [&Node](const NameMatcher &NM) {
0135       return NM.match(Node);
0136     });
0137   }
0138 
0139 private:
0140   std::vector<NameMatcher> NameMatchers;
0141 };
0142 
0143 // Returns a matcher that matches NamedDecl's against a list of provided regular
0144 // expressions. If a regular expression contains starts ':' the NamedDecl's
0145 // qualified name will be used for matching, otherwise its name will be used.
0146 inline ::clang::ast_matchers::internal::Matcher<NamedDecl>
0147 matchesAnyListedName(llvm::ArrayRef<StringRef> NameList) {
0148   return ::clang::ast_matchers::internal::makeMatcher(
0149       new MatchesAnyListedNameMatcher(NameList));
0150 }
0151 
0152 // Predicate that verify if statement is not identical to one bound to ID node.
0153 struct NotIdenticalStatementsPredicate {
0154   bool
0155   operator()(const clang::ast_matchers::internal::BoundNodesMap &Nodes) const;
0156 
0157   std::string ID;
0158   ::clang::DynTypedNode Node;
0159   ASTContext *Context;
0160 };
0161 
0162 // Checks if statement is identical (utils::areStatementsIdentical) to one bound
0163 // to ID node.
0164 AST_MATCHER_P(Stmt, isStatementIdenticalToBoundNode, std::string, ID) {
0165   NotIdenticalStatementsPredicate Predicate{
0166       ID, ::clang::DynTypedNode::create(Node), &(Finder->getASTContext())};
0167   return Builder->removeBindings(Predicate);
0168 }
0169 
0170 // A matcher implementation that matches a list of type name regular expressions
0171 // against a QualType.
0172 class MatchesAnyListedTypeNameMatcher
0173     : public ast_matchers::internal::MatcherInterface<QualType> {
0174 public:
0175   explicit MatchesAnyListedTypeNameMatcher(llvm::ArrayRef<StringRef> NameList);
0176   ~MatchesAnyListedTypeNameMatcher() override;
0177   bool matches(
0178       const QualType &Node, ast_matchers::internal::ASTMatchFinder *Finder,
0179       ast_matchers::internal::BoundNodesTreeBuilder *Builder) const override;
0180 
0181 private:
0182   std::vector<llvm::Regex> NameMatchers;
0183 };
0184 
0185 // Returns a matcher that matches QualType against a list of provided regular.
0186 inline ::clang::ast_matchers::internal::Matcher<QualType>
0187 matchesAnyListedTypeName(llvm::ArrayRef<StringRef> NameList) {
0188   return ::clang::ast_matchers::internal::makeMatcher(
0189       new MatchesAnyListedTypeNameMatcher(NameList));
0190 }
0191 
0192 } // namespace clang::tidy::matchers
0193 
0194 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_MATCHERS_H